【问题标题】:How to find all objects with an attribute that matches any of the values in another collection?如何查找具有与另一个集合中的任何值匹配的属性的所有对象?
【发布时间】:2015-09-21 10:58:33
【问题描述】:

我有一个包含对象的集合,其中一个对象属性是 PublishRequestStatus,它是一个枚举值。

我正在接收需要匹配的所有枚举值的另一个列表,现在我知道如何搜索与某个值匹配的 1 个属性:

model = model.Where(x => x.PublishRequestStatus == PublishRequestStatus.Denied);

但我无法匹配来自另一个集合的所有可能值。例如,如果我有一个包含 PublishRequestStatus.ApprovedPublishRequestStatus.Denied 的集合,我将如何使用 LINQ 搜索具有这两个枚举值中的任何一个的所有对象?

我发现唯一可行的方法是在循环中为第二个集合中的每个枚举值创建一个列表,最后将所有列表连接在一起。但是,我很确定 LINQ 有更好的方法来完成我想要实现的目标。

【问题讨论】:

    标签: c# asp.net-mvc linq select enums


    【解决方案1】:

    这可能不是您正在寻找的,而是更多的建议。除了接收List<SomeEnum>,您可以简单地在枚举值上按位使用|,然后使用Enum.HasFlags 查找它们:

    var flags = PublishRequestStatus.Approved | PublishRequestStatus.Denied;
    var otherFlags = PublishRequestStatus.Approved | 
                     PublishRequestStatus.Denied | 
                     PublishRequestStatus.MaybeApproved;
    
    Console.WriteLine(otherFlags.HasFlags(flags)); // Yields true.
    

    假设这样的事情是可能的。

    【讨论】:

    • 我查看了使用 bitflags 引起这个问题的原因 stackoverflow.com/questions/4194333/…,但是我必须更改很多现有系统。我会看看它是否值得改变,它会在我的环境中工作。
    • @anthonytimmers 祝你好运:)。它肯定会为您节省不必要的迭代。
    【解决方案2】:

    类似这样的:

    model = model.Where(x => myEnumList.Contains(x.PublishRequestStatus));
    

    或者.Any():

    model = model.Where(x => myEnumList.Any(y => y == x.PublishRequestStatus));
    

    编辑:根据 Yuvals 的回答,您也可以简单地检查您当前的元素 x 是否有任何标志:

    model = model.Where(x => x.PublishRequestStatus.HasFlags(otherFlags));
    

    这假设您的枚举类似于:

    [Flags]
    enum MyEnum { ... }
    

    这将允许按位|

    【讨论】:

    【解决方案3】:

    从性能的角度来看,最好的方法是避免引入闭包的 lambda。所以如果你有

    ICollection<PublishRequestStatus> filter = ...;
    

    其中filter 可以是List&lt;PublishRequestStatus&gt;PublishRequestStatus[] 或更好的HashSet&lt;PublishRequestStatus&gt;

    那么你可以使用method group谓词:

    model = model.Where(filter.Contains);
    

    【讨论】:

    • 过滤器是一个 PublishRequestStatus[]。我不知道你所说的引入闭包是什么意思,但我必须在空闲时间阅读一下闭包在编码方面的确切含义。模型的类型是 GamePublishRequestViewModel[]。此模型中的状态位于 Model.PublishRequest.PublishRequestStatus,所以我认为 lambda 是必要的(?),model.Where(filter.Contains) 将不起作用。
    • 每个T[]也实现了很多接口,包括ICollection&lt;T&gt;。因此,如果您有一个filter 类型为PublishRequestStatus&gt;[] 的变量,请尝试以下ICollection&lt;PublishRequestStatus&gt; c = filter; 并会看到它编译时不会出错。要将其应用于我的答案,只需使用 model.Where(((ICollection&lt;PublishRequestStatus&gt;)filter).Contains)
    • 闭包怎么样,很高兴知道并且有很多来源,包括有很好解释的 SO,但很快它是一个编译器生成的类,它被实例化并将一些局部变量作为字段保存制作需要它们工作的 lambda。例如stackoverflow.com/questions/32425833/…
    猜你喜欢
    • 1970-01-01
    • 2020-06-09
    • 2013-10-26
    • 1970-01-01
    • 1970-01-01
    • 2019-07-03
    • 2010-10-09
    • 2015-03-27
    • 2014-04-19
    相关资源
    最近更新 更多