2011-02-03 27 views
5

Giả sử tôi có hai (hoặc nhiều hơn) IEnumerable<T> với nhiều yếu tố. Mỗi IEnumerable có một loại khác T. Danh sách có thể cực kỳ dài và không được tải vào bộ nhớ một cách hoàn chỉnh.Làm thế nào tôi có thể lặp qua một số IEnumerables đồng thời

IEnumerable<int> ints = getManyInts(); 
IEnumerable<string> strings = getSomeStrings(); 
IEnumerable<DateTime> dates = getSomeDates(); 

Những gì tôi muốn làm là để lặp qua các danh sách này, và nhận được một mục có chứa một int, một chuỗi và một DateTime cho mỗi bước, cho đến khi kết thúc dài nhất hoặc danh sách ngắn nhất đã đạt được. Cả hai trường hợp nên được hỗ trợ (bool param dài nhất so với ngắn nhất hoặc lâu hơn). Đối với tất cả các mục không có trong danh sách ngắn hơn (vì kết thúc đã đạt được) tôi mong đợi các giá trị mặc định.

for(Tuple<int,string,DateTime> item in 
    Foo.Combine<int,string,DateTime>(ints, strings, dates)) 
{ 
    int i=item.Item1; 
    string s=item.Item2; 
    DateTime d=item.Item3; 
} 

Có thể thực hiện việc này với LINQ bằng cách thực hiện hoãn lại không? Tôi biết giải pháp sử dụng IEnumerators kết hợp trực tiếp với lợi nhuận. Xem How can I iterate over two IEnumerables simultaneously in .NET 2

+0

Bạn đang tìm kiếm một 'Zip' chức năng chấp nhận hơn hai tham số. – Gabe

+0

Bạn có thể dễ dàng sử dụng cái gì đó như 'var result = s1.Zip (s2.Zip (s3, (a, b) => mới {a, b}), (a, b) => mới {a = a , b = ba, c = bb}); ' – Mormegil

+0

Điều gì xảy ra nếu s2 là danh sách dài nhất và s1 chỉ có vài phần tử? –

Trả lời

4

Something như thế này nên làm điều đó (warning- chưa được kiểm tra):

public static IEnumerable<Tuple<T, U, V>> IterateAll<T, U, V>(IEnumerable<T> seq1, IEnumerable<U> seq2, IEnumerable<V> seq3) 
{ 
    bool ContinueFlag = true; 
    using (var e1 = seq1.GetEnumerator()) 
    using (var e2 = seq2.GetEnumerator()) 
    using (var e3 = seq3.GetEnumerator()) 
    { 
     do 
     { 
      bool c1 = e1.MoveNext(); 
      bool c2 = e2.MoveNext(); 
      bool c3 = e3.MoveNext(); 
      ContinueFlag = c1 || c2 || c3; 

      if (ContinueFlag) 
       yield return new Tuple<T, U, V>(c1 ? e1.Current : default(T), c2 ? e2.Current : default(U), c3 ? e3.Current : default(V)); 
     } while (ContinueFlag); 
    } 
} 
+0

Vâng, đó là những gì tôi có nghĩa là ở phần cuối của câu hỏi của tôi. Tôi hy vọng có một phương pháp linq thực hiện. –

+0

@matthias - điều này vẫn tương thích với linq và vẫn hoạt động giống như các toán tử LINQ khác. –

+0

Tôi biết, điều này tương thích với LINQ. Nó chỉ đơn giản là 'trả về' một IEnumerable khác. –

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