相交任意数量的列表

时间:2013-10-07 15:46:37

标签: c# .net linq intersection

说我有任意数量的名单

List<int> List1 = new List<int>();
List<int> List2 = new List<int>();
List<int> ListN = new List<int>();

如何获得最终列表,其中仅包含每个列表中存在的元素。

我最初用很多循环做了这个。但是我不满意。由于我对LINQ的了解有限,我认为这应该很容易,但我不知道从哪里开始。

还有其他方法可以做到这一点,最好使用LINQ。

4 个答案:

答案 0 :(得分:2)

List<List<int>> lists = new List<List<int>>{
                           List2, ..., ListN
                         };
IEnumerable<int> result = List1;
foreach(var list in lists){
  result = result.Intersect(list);
  if(!result.Any()) break;
}
//Use ToList() on result to get List<int>

答案 1 :(得分:1)

使用Intersect

var r = List1.Intersect(List2).Intersect(ListN);

示例:

var r = new [] { 1, 2, 3, 4 }
    .Intersect(new [] { 2, 3, 4, 5 })
    .Intersect(new [] { 3, 4, 5, 6 });
// r now contains 3, 4

文档:http://msdn.microsoft.com/en-us/library/bb460136.aspx

这是一个扩展方法,它获取列表列表并对它们执行所有交集。与上面相同,但也许更容易使用?

public static IEnumerable<T> IntersectAll<T>(
   this IEnumerable<T> list, 
   params IEnumerable<T>[] otherLists
) {
    foreach (var otherList in otherLists)
    {
        list = list.Intersect(otherList);
    }
    return list;
}

用法:

var r = new [] { 1, 2, 3, 4 }
     .IntersectAll(new [] { 2, 3, 4, 5 }, new [] { 3, 4, 5, 6 });

答案 2 :(得分:0)

非常简单:

var intersection = List1.Intersect(List2).Intersect(List3);

或者,如果您想轻松支持 n 数量的列表:

var lists = new List<List<string>>();

lists.Add(new List<string>(new string[] { "Test1", "Test2", "Test3" }));
lists.Add(new List<string>(new string[] { "Test1", "Test2", "Test4" }));
lists.Add(new List<string>(new string[] { "Test1", "Test2", "Test5" }));
lists.Add(new List<string>(new string[] { "Test1", "Test2", "Test6" }));

var aggregate = lists.Aggregate((x, y) => x.Intersect(y).ToList());

答案 3 :(得分:0)

虽然您可以使用LINQ的Intersect方法,但这将导致不断获取当前的交集并使用这些项重新填充新的HashSet。通过使用您自己的显式HashSet,您可以更有效地获得N个序列的交集:

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

        var set = new HashSet<T>(iterator.Current);
        while (iterator.MoveNext())
            set.IntersectWith(iterator.Current);

        return set;
    }
}