我有一个列表的列表:
List<Tuple<string, List<SomeObject>>
我想选择所有在上述列表的每一行中都存在的SomeObjects
。
有些对象只存在于一个或两个列表中,但我想要存在于每个列表中的所有对象,而且其他对象被舍弃。
我无法找到一种优雅的解决方案,而不需要大量使用C#代码。有没有更好的方法?
list.Select (x => x.Item2 as IEnumerable<SomeObject>)
.Aggregate((x,y)=> x.Intersect(y))
.ToList();
或者像Jeppe Stig Nielsen建议的那样(我认为这更加优雅):
list.Select(x => x.Item2.AsEnumerable())
.Aggregate(Enumerable.Intersect)
.ToList();
as IEnumerable<SomeObject>
- dcastrolist.Select(x => x.Item2.AsEnumerable()).Aggregate(Enumerable.Intersect).ToList();
。 - Jeppe Stig NielsenAggregate<>
相关的重载只有一个类型参数 TSource
。您需要让 TSource
成为 IEnumerable<SomeObject>
,而不是 List<SomeObject>
。因此,包含 "as enumerable" 可以帮助解决这个问题。当然,另一种选择是显式地给出类型参数。强调一下,也可以使用 TSource == List<SomeObject>
:list.Select(x => x.Item2).Aggregate((x, y) => x.Intersect(y).ToList());
(不建议使用,每次迭代都会创建新的 List<>
实例)。 - Jeppe Stig Nielsenvar results = source.First().Item2
foreach (var element in source.Skip(1) )
{
results = results.Intersect(element.Item2)
}
static IEnumerable<TSource> IntersectMany<TSource>(this IEnumerable<IEnumerable<TSource>> sources)
{
return sources.Aggregate(Enumerable.Intersect);
}
var result = list.Select(x => x.Item2).IntersectMany();
它之所以有效,是因为IEnumerable<out T>
在T
方面是协变的(C# 4,.NET 4.0)。
假设该类重写了Equals
和GetHashCode
方法或您拥有自定义的IEqualityComparer<SomeObject>
,则可以使用以下查询,它使用Enumerable.All
:
var result = list
.SelectMany(t => t.Item2) // select all objects
.Distinct() // just an optimization since duplicates are guaranteed
.Where(obj => list.All(t => t.Item2.Contains(obj)));
这是我的样本数据:
var list = new List<Tuple<string, List<SomeObject>>>();
list.Add(Tuple.Create("a", new List<SomeObject> { new SomeObject { ID = 1 }, new SomeObject { ID = 2 }, new SomeObject { ID = 4 } }));
list.Add(Tuple.Create("b", new List<SomeObject> { new SomeObject { ID = 1 }, new SomeObject { ID = 2 }, new SomeObject { ID = 3 } }));
list.Add(Tuple.Create("c", new List<SomeObject> { new SomeObject { ID = 1 }, new SomeObject { ID = 2 }, new SomeObject { ID = 3 } }));
list.Add(Tuple.Create("d", new List<SomeObject> { new SomeObject { ID = 1 }, new SomeObject { ID = 2 }, new SomeObject { ID = 3 } }));
只有ID为1或2的SomeObjects
在所有列表中,这是查询结果。
.SelectMany
吗? - danludwig