LINQ 在内部集合上相交
本文关键字:集合 在内部 LINQ | 更新日期: 2023-09-27 18:37:21
我有一个存储列表(类型为 ObservableCollection<Store>
),Store
对象有一个名为 Features 的属性(类型 List<Feature>
)。 并且Feature
对象具有 Name 属性(类型 string
)。
回顾一下,包含功能列表的商店列表
我有第二个所需功能集合(类型List<string>
)。
我需要使用 LINQ 仅向我提供具有所有所需功能的存储的结果。到目前为止,我只能提出一个查询,给我一个OR结果而不是AND。
如下所示:
var q = Stores.Where(s=> s.Features.Any(f=> DesiredFeatures.Contains(f.name)));
我知道Intersect
可以提供帮助,以下是我的使用方式:
var q = Stores.Where(s => s.Features.Intersect<Feature>(DesiredFeatures));
这就是我卡住的地方,相交想要一个Feature
对象,我需要相交的是 Feature.Name。
目标是最终得到一个可观察的集合,其中每个商店都有所有所需的功能。
谢谢!
你几乎已经完成了你需要的。一个小的改进是交换DesiredFeatures
和s.Features
。
var q = Stores.Where(s => DesiredFeatures.All(df => s.Features.Contains(df)));
这意味着仅采用那些所需功能都包含在商店功能中的商店。
我需要使用 LINQ 仅向我提供具有所有所需功能的存储的结果。
换句话说,每个所需功能都必须具有匹配的存储功能。
在这种情况下,我不明白Intersect
如何提供帮助。将上述条件直接转换为 LINQ 的过程如下所示:
var q = Stores.Where(s =>
DesiredFeatures.All(df => s.Features.Any(f => f.Name == df))
);
更有效的方法是使用 GroupJoin 来执行匹配:
var q = Stores.Where(s =>
DesiredFeatures.GroupJoin(s.Features,
df => df, sf => sf.Name, (df, sf) => sf.Any()
).All(match => match)
);
或"检查不匹配的项目除外":
var q = Stores.Where(s =>
!DesiredFeatures.Except(s.Features.Select(sf => sf.Name)).Any()
);
按照你的交叉想法,我想到做这项工作的唯一方法是使用Select
将Store.Features(List<Feature>
)作为功能名称(List<string>
)的列表,并将其与DesiredFeatures相交。
更新的答案:
var q = Stores.Where(s => s.Features.Select(f => f.Name).Intersect(DesiredFeatures).Any());
或
var q = Stores.Where(s => DesiredFeatures.Intersect(s.Features.Select(f => f.Name)).Any());
旧答案(如果需要功能是一个List<Feature>
):
var q = Stores.Where(s => s.Features.Select(f => f.Name).Intersect(DesiredFeatures.Select(df => df.Name)).Any());
代码执行的两件事。
var q = Stores.Where(s=> s.Features.All(f=> DesiredFeatures.Contains(f.name)) &&
s.Features.Count() == DesiredFeatures.Count()); // Incude Distinct in the comparison if Features list is not unique
- 确保每个功能都是所需的功能
- 商店包含所有所需的功能。
上面的代码假设Features
集合和DesiredFeatures
中的唯一性,如果不正确,请按照注释行中所述修改代码