【问题标题】:LINQ query to search multiple conditions in a specific order?LINQ查询以特定顺序搜索多个条件?
【发布时间】:2014-11-21 23:24:20
【问题描述】:

我有一组静态类别,以及一个传入的不同类别的项目列表。我想获取与最佳类别匹配的第一个项目,如果没有找到,则获取与次佳类别匹配的第一个项目,等等,直到我到达默认类别。

我尝试将我的类别放入一个 IEnumerable 并对其执行Contains() 以查看我传入的项目是否与某个类别匹配,并在第一个匹配项时停止。但我无法控制匹配顺序:如果类别列表按优先级排序[best, OK, default],则类别列表中与 anything 匹配的第一个输入项获胜。因此,如果我的第一个输入项匹配OK,而第二个输入项匹配Best,那么我将在获得Best 匹配之前停止。

现在我在项目列表上运行Where(),如果结果为空,我运行第二个Where(),等等。我想知道是否有更简洁(或更多 LINQ 惯用)的方式写这个:

    public MyVM getVM( IEnumerable<Entities.Foo> foos )
    {
        Entities.Foo foo  = null;
        MyVM         myVM = null;

        if ( entity.IsBar ) 
        {
            foo = foos.Where( f => f.FooCatId == FooCategories.BestCat ).FirstOrDefault();
        }

        // no foos are BestCat, look for OkCat
        if ( foo == null ) 
        {
            foo = foos.Where( f => f.FooCatId == FooCategories.OkCat ).FirstOrDefault();
        }

        // no foos are OkCat, look for DefaultCat
        if ( foo == null ) 
        {
            foo = foos.Where( f => f.FooCatId == FooCategories.DefaultCat ).FirstOrDefault();
        }

        if ( foo != null ) 
        {
            myVM = new MyVM() { Name = foo.Name };
        }
        return myVM;
    }

    public enum FooCategories
    {
        DefaultCat,
        SomeCat,
        AnotherCat,
        OkCat,
        BestCat,
        BadCat
    }

【问题讨论】:

    标签: c# linq linq-to-objects


    【解决方案1】:

    当然有更简洁的方法,有两种方式:

    • 使用带有谓词的FirstOrDefault 的重载
    • 使用空合并运算符

    我将暂时忽略您的 IsBar 检查,因为我不明白它是如何适应的……但剩下的就是:

    var foo = foos.FirstOrDefault(f => f.FooCatId == FooCategories.BestCat)
           ?? foos.FirstOrDefault(f => f.FooCatId == FooCategories.OkCat)
           ?? foos.FirstOrDefault(f => f.FooCatId == FooCategories.DefaultCat);
    

    另一种选择是更改您的枚举顺序,以便您可以找到具有最佳类别的猫 - 使用 OrderByDescending(f =&gt; f.FooCatId) 或使用 MoreLINQ 中的 MaxBy。然后,您还需要检查生成的猫是否不是坏猫,等等,所以这可能不是什么大赢家——但MaxBy 至少会更有效率,只需浏览一次列表即可。

    【讨论】:

    • 哦,我忘记了 FirstOrDefault 的谓词重载!我尝试了 null-coalescing 运算符,但我的谓词在前面的 Where 子句中,它不起作用。不用担心 IsBar——我在匿名代码时错过了这一点;这只是获得首选类别的条件。在这种情况下,我无法重新排序传入列表,但我可以重新排序枚举,所以我也会玩这个,但正如你所说,我认为到我理智的时候那里并没有太大的收获检查。感谢您的提示 -- 很荣幸得到您的答复!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多