Linq查询以获取子列表中的共享项
本文关键字:共享 列表 查询 获取 Linq | 更新日期: 2023-09-27 18:20:41
我有一个类,它的属性是List,我将把这个类命名为a。然后我有了一个List<A>
。
我需要对象的LINQ来获取List<A>
上所有项目上存在的所有对象B。
需要澄清的示例:
var list = new List<A>
{
new A { B = new List<B> { B1, B2, B3, B4 } }
new A { B = new List<B> { B3, B4, B5, B6 } }
new A { B = new List<B> { B2, B3, B4, B5, B6 } }
};
查询必须返回对象B3和B4,因为它们是所有List<A>
对象中唯一包含的对象。
如果你有一个列表列表,并且你想要所有内部列表中的元素,你可以使用Aggregate
和Intersect
的组合,如下所示:
IEnumerable<IEnumerable<string>> listOfLists = new string[][] {
new string[] { "B1", "B2", "B3", "B4" },
new string[] { "B3", "B4", "B5", "B6" },
new string[] { "B2", "B3", "B4", "B5", "B6" }
};
IEnumerable<string> commonElements = listOfLists.Aggregate(Enumerable.Intersect);
只要至少有一个元素,并且类B
具有等式/GetHashCode()
:的充分实现,就可以使用Intersect()
IEnumerable<B> allBs = list[0].B;
foreach (var item in list.Skip(1))
{
allBs = allBs.Intersect(item.B);
}
除了增加复杂性之外,我认为"纯"Linq解决方案没有任何好处。
只要为类型B的对象正确定义了Equals/GetHashCode,那么这实际上有点简单:
_listToQuery.Aggregate(
_listToQuery.First().B,
(seed, nextItem) => { seed = seed.Intersect(nextItem.B); return seed; })
或者,另一种方式:
_listToQuery.SelectMany(tr => tr.B)
.GroupBy(tr => tr)
.Where(tr => tr.Count() == _listToQuery.Count)
.Select(tr => tr.Key)
我处理这一问题的方法是创建一个所有B的列表,然后通过某个唯一标识符(如果它们是可比较的,则仅为对象)对它们进行分组,找出哪些B不止一次出现。分组后,选择实例数大于1的实例,使用每个分组的第一个实例作为规范代表。
var selection = list.SelectMany( a => a.B )
.GroupBy( b => b.UniqueID, b => b )
.Where( b => b.Count() > 1 )
.Select( b => b.First() );