我的情况是我生成了许多包含整数值的列表。但是,这些列表的数量仅在运行时已知,并且结果列表中存在的整数必须存在于所有列表中。有没有一种方法可以将所有这些列表合并到一个列表中?
即
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或任何其他方法吗?
答案 0 :(得分:5)
我假设您的List<List<int>>
包含可变数量的List<int>
。
你可以intersect第一个列表和第二个列表
var intersection = listOfLists[0].Intersect(listOfLists[1]);
然后将结果与第三个列表相交
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);
}
var intersection = listOfLists.Aggregate(Enumerable.Intersect);
如果订单不重要,那么您还可以使用第一个列表填充的HashSet<T>和剩余列表intersect with(如 @Servy 所示) )。
var intersection = new HashSet<int>(listOfLists.First());
foreach (List<int> list in listOfLists.Skip(1))
{
intersection.IntersectWith(list);
}
答案 1 :(得分: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();
答案 2 :(得分: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);
}