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。

目标是最终得到一个可观察的集合,其中每个商店都有所有所需的功能。

谢谢!

LINQ 在内部集合上相交

你几乎已经完成了你需要的。一个小的改进是交换DesiredFeaturess.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中的唯一性,如果不正确,请按照注释行中所述修改代码