3

整数値を含む多数のリストを生成した状況があります。ただし、これらのリストの数は実行時にのみわかり、結果のリストに存在する整数はすべてのリストに存在する必要があります。これらすべてのリストを 1 つのリストに結合する方法はありますか?

すなわち

List<int> l1 = {1, 2, 3, 4};
List<int> l2 = {2, 3, 5, 7, 9};
List<int> l3 = {3, 9, 10};
List<int> ln = {....};

結果のリストは次のようになります

List<int> r = {3};

これはlinqまたは他の方法で可能ですか?

4

3 に答える 3

5

List<List<int>>の可変数を保持するがあると仮定しますList<int>

最初のリストと 2 番目のリストを交差させることができます

var intersection = listOfLists[0].Intersect(listOfLists[1]);

そして、結果を3番目のリストと交差させます

intersection = intersection.Intersect(listOfLists[2]);

intersectionなど、すべてのリストの交点が保持されるまで続きます。

intersection = intersection.Intersect(listOfLists[listOfLists.Count - 1]);

forループの使用:

IEnumerable<int> intersection = listOfLists[0];

for (int i = 1; i < listOfLists.Count; i++)
{
    intersection = intersection.Intersect(listOfLists[i]);
}

foreachループの使用( @lazyberezovskyで示されているように):

IEnumerable<int> intersection = listOfLists.First();

foreach (List<int> list in listOfLists.Skip(1))
{
    intersection = intersection.Intersect(list);
}

Enumerable.Aggregate の使用:

var intersection = listOfLists.Aggregate(Enumerable.Intersect);

順序が重要でない場合は、最初のリストを入力し、残りのリストと交差するHashSet<T>を使用することもできます ( @Servyで示されています)。

var intersection = new HashSet<int>(listOfLists.First());

foreach (List<int> list in listOfLists.Skip(1))
{
    intersection.IntersectWith(list);
}
于 2013-02-20T16:29:55.753 に答える
1
// lists is a sequence of all lists from l1 to ln
if (!lists.Any())
   return new List<int>();

IEnumerable<int> r = lists.First();   

foreach(List<int> list in lists.Skip(1))    
   r = r.Intersect(list);

return r.ToList();
于 2013-02-20T16:29:53.050 に答える
0

コレクションのコレクションの交差を取得する簡単な方法を次に示します。

public static IEnumerable<T> Intersect<T>(IEnumerable<IEnumerable<T>> sequences)
{
    using (var iterator = sequences.GetEnumerator())
    {
        if (!iterator.MoveNext())
            return Enumerable.Empty<T>();

        HashSet<T> intersection = new HashSet<T>(iterator.Current);

        while (iterator.MoveNext())
            intersection.IntersectWith(iterator.Current);

        return intersection;
    }
}

ここでの考え方は、すべてのアイテムをセットに入れ、そのセットを各シーケンスと順番に交差させることです。単純な LINQ を使用してはるかに少ないコードでこれを行うことができますが、これはHashSet単一の交差点を再利用するのではなく、各交差点の結果から新しいものを取り込むことになるため、非常にエレガントに見えますが、オーバーヘッドが大幅に高くなります。

パフォーマンスは劣りますが、より洗練されたソリューションを次に示します。

public static IEnumerable<T> Intersect<T>(IEnumerable<IEnumerable<T>> sequences)
{
    return sequences.Aggregate(Enumerable.Intersect);
}
于 2013-02-20T16:37:19.527 に答える