2010-03-24 18 views
7

Tôi muốn thêm hai danh sách của một số loại như vậy addedList [x] = listOne [x] + listTwo [x]Làm cách nào để thêm hai danh sách vào Linq để thêmList [x] = listOne [x] + listTwo [x]?

Sản lượng của danh sách cần phải được một Generic.IEnumerable mà tôi có thể sử dụng trong các truy vấn LINQ trong tương lai.

Trong khi tôi có thể làm điều đó bằng cách sử dụng mã bên dưới, tôi không thể không cảm thấy như phải có một cách tốt hơn. Bất kỳ ý tưởng?

List<int> firstList = new List<int>(new int[] { 1, 3, 4, 2, 5, 7, 2, 5, 7, 8, 9, 0 }); 
List<int> secondList = new List<int>(new int[] { 4, 6, 8, 3, 1, 5, 9, 3, 0 }); 

int findex = 0; 

ILookup<int, int> flookup = firstList.ToLookup(f => 
          { 
           int i = findex; 
           findex++; 
           return i; 
           }, p => p); 

var listsAdded = from grp in flookup 
       select grp.First() + secondList.ElementAtOrDefault(grp.Key); 

foreach (int i in listsAdded) 
    Console.WriteLine(i); 
+0

Điều gì sẽ xảy ra khi danh sách thứ hai dài hơn lần đầu tiên? – Gabe

+0

@gabe - xem giải pháp của tôi bên dưới, nó xử lý danh sách có độ dài khác nhau. –

Trả lời

3
var result = 
    from i in 
     Enumerable.Range(0, Math.Max(firstList.Count, secondList.Count)) 
    select firstList.ElementAtOrDefault(i) + secondList.ElementAtOrDefault(i); 
+0

Đây chính xác là những gì tôi đang tìm kiếm. Cảm ơn Artem. – Audie

+0

Cảnh báo - Cách tiếp cận này có thể không hiệu quả khủng khiếp - đặc biệt đối với các danh sách có kích thước đáng kể. Mỗi cuộc gọi đến 'ElementAtOrDefault' có thể cần phải lặp qua danh sách từ đầu. Kết hợp hai danh sách 100 phần tử có thể phải chịu chi phí của việc lặp lại 10,100 phần tử thay vì chỉ 200. Đối với 1000 phần tử, nó sẽ trở thành 1.001.000 phần tử. Và nó chỉ trở nên tồi tệ hơn một cách nhanh chóng từ đó ... – Enigmativity

+2

@Enigmativity, điều này là không đúng trong bối cảnh nhất định. Xem xét rằng ElementAtOrDefault được gọi cho danh sách (IList nói chung) - kích thước của danh sách không thực sự quan trọng bởi vì ElementAtOrDefault (index) thực hiện nội bộ là danh sách gọi [index] để truy cập danh sách mảng nội bộ theo chỉ mục, do đó truy cập là O (1) và không lặp lại bất cứ điều gì như bạn đang nói. ElementAtOrDefault có thể hoạt động giống như bạn đã chỉ ra cho những người IEnumerable không thuộc loại IList (nhưng đây không phải là trường hợp của câu hỏi này). –

0
var res = list.Concat(list1); 

nối hai danh sách, bao gồm cả các bản sao cuối cùng.

var res = list.Union(list1); 

ghép hai danh sách, cung cấp kết quả không trùng lặp.

3

Có vẻ như bạn muốn có một chức năng như thế này:

public static IEnumerable<int> SumIntLists( 
    this IEnumerable<int> first, 
    IEnumerable<int> second) 
{ 
    using(var enumeratorA = first.GetEnumerator()) 
    using(var enumeratorB = second.GetEnumerator()) 
    { 
     while (enumeratorA.MoveNext()) 
     { 
      if (enumeratorB.MoveNext()) 
       yield return enumeratorA.Current + enumeratorB.Current; 
      else 
       yield return enumeratorA.Current; 
     } 
     // should it continue iterating the second list? 
     while (enumeratorB.MoveNext()) 
      yield return enumeratorB.Current; 
    } 
} 
+0

Cảm ơn Gabe. Đây là một ví dụ tuyệt vời về một phần mở rộng có thể giải quyết được vấn đề của tôi. Tôi hy vọng có thể làm được điều này mà không cần viết một phần mở rộng, như Artem đã làm. Ví dụ về tiện ích mở rộng của bạn mang tính hướng dẫn và tôi thích cách bạn xử lý các độ dài danh sách khác nhau. Cảm ơn bạn đã giúp đỡ. – Audie

15

gì bạn đang tìm kiếm là một phương pháp Zip. Phương pháp này cho phép bạn kết hợp với các danh sách có độ dài bằng nhau thành một danh sách đơn bằng cách áp dụng phép chiếu.

Ví dụ

var sumList = firstList.Zip(secondList, (x,y) => x + y).ToList(); 

Phương pháp này đã được thêm vào BCL trong CLR 4.0 (Reference). Nó khá thẳng về phía trước để thực hiện mặc dù và nhiều phiên bản có sẵn trực tuyến có thể được sao chép vào một ứng dụng 2.0 hoặc 3.5.

+0

Zip xử lý các chuỗi có kích thước khác nhau như thế nào? – Gabe

+0

@gabe, các triển khai khác nhau thực hiện các tuyến đường khác nhau. Phiên bản BCL sẽ bỏ qua các phần tử phụ trong danh sách dài hơn nhưng khá dễ dàng để viết một phương thức khác mở rộng danh sách. – JaredPar

Các vấn đề liên quan