2012-05-30 16 views
5

Cho phép nói rằng tôi có một đối tượng chứa tên người và thành phố của họ.Tìm các kết hợp của một danh sách được nhóm bằng cách sử dụng LINQ trong C#

public class personDetails 
{ 
    public string City; 
    public string Name; 
} 

Và tôi có danh sách có các mục nhập sau được thêm vào.

Name City 
John | London 
Jane | London 
Tom | New York 
Bob | New York 
Fred | New York 

Điều tôi đang tìm kiếm là tất cả các kết hợp có thể có tên, được nhóm theo thành phố.

John Tom 
John Bob 
John Fred 
Jane Tom 
Jane Bob 
Jane Fred 

tôi có thể làm điều này nếu tôi biết trước số lượng các nhóm, bằng cách sử dụng đoạn mã sau

List<personDetails> personList = new List<personDetails>(); 
//populate list 

var groupedPersons = personList.GroupBy(c => c.City); 
foreach (var item1 in groupedPersons[0]) 
{ 
    foreach (var item2 in groupedPersons[1]) 
    { 
     Console.WriteLine(item1.Name + " " + item2.Name); 
    }   
} 

Tuy nhiên, chỉ có các công trình này nếu tôi biết số lượng các nhóm trước, và nhanh chóng trở nên khó sử dụng khi số lượng các nhóm phát triển lớn hơn. Tôi chắc chắn rằng có một cách thanh lịch để làm điều này bằng cách sử dụng LINQ, ai có thể làm sáng tỏ một số?

+0

Hãy xem câu trả lời này http://stackoverflow.com/questions/9168269/permutation-algorithms-in-c-sharp. Bạn có thể tham gia danh sách của bạn với chính nó. – Brad

+0

@Brad Điều đó sẽ phù hợp với ví dụ được liệt kê với 2 thành phố. Những gì OP muốn là một sản phẩm thập chiều N, trong đó N không được biết cho đến khi chạy. Đoạn mã đó không cung cấp. – Servy

Trả lời

3

Chúng tôi sẽ bắt đầu với đoạn mã sau được lấy nguyên văn từ here. (Đó là một liên kết tốt, đáng đọc).

public static class MyExtensions 
{ 
    public static IEnumerable<IEnumerable<T>> CartesianProduct<T>(this IEnumerable<IEnumerable<T>> sequences) 
    { 
     IEnumerable<IEnumerable<T>> emptyProduct = new[] { Enumerable.Empty<T>() }; 
     return sequences.Aggregate(
      emptyProduct, 
      (accumulator, sequence) => 
      from accseq in accumulator 
      from item in sequence 
      select accseq.Concat(new[] { item })); 
    } 
} 

Sau đó tất cả chúng ta cần phải làm là:

var groupedPersons = personList.GroupBy(c => c.City) 
    //need an enumerable of enumerables, not an enumerable of groupings, 
    //because the method isn't covariant. 
    .Select(group => group.AsEnumerable()); 

var results = groupedPersons.CartesianProduct(); 
foreach (var group in results) 
{ 
    foreach (var person in group) 
    { 
     Console.Write(person.Name + " "); 
    } 
    System.Console.WriteLine(); 
} 
+0

OK, đã kiểm tra sau khi nhập dữ liệu bạn đã cung cấp và in kết quả mong đợi. – Servy

+0

Tuyệt vời, hoạt động tuyệt vời. Và một liên kết rất thú vị để khởi động, cảm ơn rất nhiều. – John

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