【问题标题】:Linq query - Tidy Up/OptimizationLinq 查询 - 整理/优化
【发布时间】:2013-10-07 08:43:29
【问题描述】:

我正在使用以下代码行:

ListOfMyClass.OrderByDescending(x => x.DateCreated)
             .Where(x => !x.Deleted).First();

我明白了

“替换为对第一个警告的单次调用”

我更愿意这样做,但不知道怎么做。

我希望能够说明创建日期为最新且标记为未删除的项目。

在哪里学习这类查询的最佳地点以及解决这个问题的最佳方法是什么,因为我更喜欢成为一名整洁的编码员。

【问题讨论】:

  • 这是什么:Replace with single call to first warning?我怀疑这是确切的警告。除此之外,还有什么工具会发出该警告?
  • @TimSchmelter,我认为这是来自 ReSharper 的警告。

标签: c# linq list


【解决方案1】:

我会将Where 放在第一位,因此要排序的项目更少。

ListOfMyClass.Where(x => !x.Deleted).OrderByDescending(x => x.DateCreated).First();

另外,您可能想使用 MaxBy 来自 MoreLinq:

ListOfMyClass.Where(x => !x.Deleted).MaxBy(x => x.DateCreated);

【讨论】:

  • @Liam 我不确定。我假设OrderByDescending 读取所有项目并将它们排序为 O(nlogn)。
  • 我认为这取决于。如果它是 Linq to Objects 你的权利,如果它是 Linq to SQL 延迟加载将创建单个 SQL 语句,这将不起作用。我猜这是 Linq to objects 所以它是相关的。
【解决方案2】:

你可以在没有 where 的情况下调用它:

ListOfMyClass.OrderByDescending(x => x.DateCreated).First(x => !x.Deleted);

First 也接受谓词。在这种情况下,你写 WhereFirst 还是只写 First 真的没关系,它会被评估为相同的查询:) 但是 First 看起来更干净。

正如 Jeroen van Langen 所说,WhereFirst 稍快。所以我认为使用Where.OrderByDescending.First 是迄今为止最好的解决方案。

【讨论】:

  • 我认为它不需要降序排列,因为您可以使用 first 提取最新的日期值,这只是我被卡住的方法吗?
  • @LmC 单次调用第一个警告意味着您可以将 Where.First 替换为 First :)
  • 我不会在 First() 中执行 Where。在这里查看更多信息:stackoverflow.com/questions/8663897/…
【解决方案3】:

...最新的创建日期并标记为已删除...

如果您想要最新的、已删除的项目,为什么要要求未删除的 (!x.Deleted)?

我建议这样做:

var yourClassOrNull = ListOfMyClass
    .Where(x => x.Deleted)
    .OrderByDescending(x => x.DateCreated)
    .FirstOrDefault();

这是可读、安全和高效的。这是安全的,因为FirstOrDefault 返回与OrderByDescending 排序的Where 中的条件匹配的第一个项目。如果没有项目符合条件,则返回默认值,以防引用类型像这里null。所以你可以稍后查看if(yourClassOrNull != null) ...

这很有效,因为在 Linq-To-Objects 中过滤后进行排序很重要。

【讨论】:

  • 我认为OrderByDescending 后跟First(OrDefault) 既不可读也不高效。这就是为什么在 MoreLinq 中有一个 MaxBy 扩展方法。
  • @Henrik:它和 sql 一样可读。并且MaxBy 更有效,但它甚至不清楚它是否是Linq-To-Objects,我假设他只想要.NET 方法的答案。此外,如果.Where(x => x.Deleted) 只退回少量商品,订购它们并不昂贵。
【解决方案4】:
ListOfMyClass.Where(x=> !x.Deleted).OrderByDescending(x=>x.DateCreated).First();

【讨论】:

    【解决方案5】:

    要“满足”警告,您可以将其重写为:

    ListOfMyClass.OrderByDescending(x => x.DateCreated)
                 .First(x => !x.Deleted);
    

    但我更喜欢在排序之前进行过滤,所以我会使用这个:

    ListOfMyClass
                 .Where(x => !x.Deleted)
                 .OrderByDescending(x => x.DateCreated)
                 .First();
    

    【讨论】:

    • 排序前过滤有什么好处
    • @LmC,忽略我之前的声明。如果这是 Linq 到对象(我假设它是),那么 where 等的顺序是相关的 see here
    【解决方案6】:

    这只是使用Firstthe other overload 的建议,它接受内联谓词。这允许您将 .Where(...).First() 替换为 .First(...)

    ListOfMyClass.OrderByDescending(x => x.DateCreated).First(x => !x.Deleted);
    

    也就是说,编写查询的更好方法是

    ListOfMyClass.Where(x => !x.Deleted)
                 .OrderByDescending(x => x.DateCreated)
                 .First();
    

    这里上面的“代码编写优化”不适用,但是这个版本过滤之前排序。这可以大大加快排序速度,具体取决于过滤掉的项目百分比。对您将忽略的元素进行排序确实没有意义。

    【讨论】:

    • 我认为它不需要降序排列,因为您可以使用 first 提取最新的日期值,这只是我被卡住了怎么办?
    • @LmC:不,需要订购。
    • 我认为在订购前使用 Where 是可行的方法。 +1
    猜你喜欢
    • 2019-04-15
    • 1970-01-01
    • 1970-01-01
    • 2021-06-14
    • 1970-01-01
    相关资源
    最近更新 更多