5

人の名前と出身地を含むオブジェクトがあるとします。

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

そして、次のエントリが追加されたリストがあります。

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

私が探しているのは、都市ごとにグループ化された、考えられるすべての名前の組み合わせです。

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

グループの数が事前にわかっている場合は、次のコードを使用してこれを行うことができます

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);
    }          
}

ただし、これはグループの数が事前にわかっている場合にのみ機能し、グループの数が増えるとすぐに扱いにくくなります。LINQを使用してこれを行うエレガントな方法があると確信しています。誰か光を当てることができますか?

4

1 に答える 1

3

here からそのまま引用した次のコード スニペットから始めます。(これは良いリンクであり、読む価値があります)。

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 }));
    }
}

その後、必要なことは次のとおりです。

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();
}
于 2012-05-30T20:04:18.297 に答える