LINQ交叉,多个列表,一些空

我正试图找到与LINQ的交叉点。

样品:

List int1 = new List() { 1,2 }; List int2 = new List(); List int3 = new List() { 1 }; List int4 = new List() { 1, 2 }; List int5 = new List() { 1 }; 

想要返回:1,因为它存在于所有列表中..如果我运行:

 var intResult= int1 .Intersect(int2) .Intersect(int3) .Intersect(int4) .Intersect(int5).ToList(); 

它返回任何内容,因为1显然不在int2列表中。 无论一个列表是否为空,如何使其工作?

使用上面的例子或:

 List int1 = new List() { 1,2 }; List int2 = new List(); List int3 = new List(); List int4 = new List(); List int5 = new List(); 

在这种情况下如何返回1和2.如果列表已填充,我不知道提前…

如果您只需一步即可完成,最简单的解决方案是过滤掉空列表:

 public static IEnumerable IntersectNonEmpty(this IEnumerable> lists) { var nonEmptyLists = lists.Where(l => l.Any()); return nonEmptyLists.Aggregate((l1, l2) => l1.Intersect(l2)); } 

然后,您可以在列表或其他IEnumerable的集合上使用它:

 IEnumerable[] lists = new[] { l1, l2, l3, l4, l5 }; var intersect = lists.IntersectNonEmpty(); 

您可能更喜欢常规的静态方法:

 public static IEnumerable IntersectNonEmpty(params IEnumerable[] lists) { return lists.IntersectNonEmpty(); } var intersect = ListsExtensionMethods.IntersectNonEmpty(l1, l2, l3, l4, l5); 

您可以编写扩展方法来定义该行为。 就像是

 static class MyExtensions { public static IEnumerable IntersectAllIfEmpty(this IEnumerable list, IEnumerable other) { if (other.Any()) return list.Intersect(other); else return list; } } 

所以下面的代码将打印1。

 List list1 = new List() { 1, 2 }; List list2 = new List(); List list3 = new List() { 1 }; foreach (int i in list1.IntersectAllIfEmpty(list2).IntersectAllIfEmpty(list3)) Console.WriteLine(i); 

更新:

Anon在对这个问题的评论中提出了一个很好的观点。 如果list本身为空,则上述函数导致空集,这应该是期望的。 这意味着如果方法链中的第一个列表任何交集的结果集为空,则最终结果将为空。

要允许空的第一个列表不是空的结果集,您可以采用不同的方法。 这是一个不是扩展方法的方法,而是采用一系列IEnumerables的params数组,然后首先过滤掉空集,然后尝试与其余部分相交。

 public static IEnumerable IntersectAllIfEmpty(params IEnumerable[] lists) { IEnumerable results = null; lists = lists.Where(l => l.Any()).ToArray(); if (lists.Length > 0) { results = lists[0]; for (int i = 1; i < lists.Length; i++) results = results.Intersect(lists[i]); } else { results = new T[0]; } return results; } 

你会像这样使用它

 List list0 = new List(); List list1 = new List() { 1, 2 }; List list2 = new List() { 1 }; List list3 = new List() { 1,2,3 }; foreach (int i in IntersectAllIfEmpty(list0, list1, list2, list3)) { Console.WriteLine(i); }