Linq - orderby递减和取(1),它将返回最大项目

本文关键字:返回 项目 orderby Linq | 更新日期: 2023-09-27 18:16:29

我有这一行c#代码:

datavals
  .GroupBy(x => new { x.ElementID, x.OutputTableCode})
  .SelectMany(x => x
     .OrderByDescending(y => y.Sequence)
     .Take(1))
  .ToList<TransactionValue<string>>();

思路是将列表中的项目按ElementIDOutputTableCode分组,然后按降序顺序对每组进行排序,并且每组只返回一个项目。(这实际上是在return语句中,因此修改后的列表将返回给调用函数。)

我的问题是,这会返回具有最大序列的项目,还是不一定是这样?在我的测试示例中,它可以,但不确定它是否得到保证。

如果它不一定返回每个组中具有最大序列的项,我如何更改查询以做到这一点?

Linq - orderby递减和取(1),它将返回最大项目

如果sequence为空,则总是返回序列的最大值或空序列。

我们现在不知道序列的顺序,所以如果我们按desc -排序,我们将得到一个按desc排序的序列(最大值-第一个,最小值-最后一个)。执行.Take(1)等于执行.FirstOrDefault(),因此我们将得到序列的最大值。

如果您对.Take()有疑问,您可以使用.FirstOrDefault().First()来检索序列的第一个值。

如果你只想获得最大值,你可以使用linq .Max(),在这里你可以设置比较器属性,例如.Max(x => x.Sequence)

是的,您的代码将返回每组中序列最大的项。


这里是一个解释,让你更好地理解你的代码:

  • GroupBy将简单地对项目进行分组。分组将在{ x.ElementID, x.OutputTableCode}组合上。
  • 然后,SelectMany call将:
    • 首先,按Sequence
    • 的降序对每组进行排序
    • Take()为各组Sequence值最高的x
  • 最后,ToList会给你选择的x每个组作为List<TransactionValue<string>>

为了简化,只需使用OrderBy并使用LastOrDefault获取最后一项。另外,你必须使用Select

来代替SelectMany
   datavals.GroupBy(x => new { x.ElementID, x.OutputTableCode})
           .Select(x => x.OrderBy(y => y.Sequence)
           .LastOrDefault()).ToList<TransactionValue<string>>();

我的问题是,这会返回具有最大序列的项目,还是不一定是这样?在我的测试示例中,它可以,但不确定它是否得到保证。

是的。它将始终返回序列最大的项。因为它是有序的,而你取的是最后一件物品,所以最后一件物品不可能没有最大Sequence

不如使用这个查询,因为它更易于阅读和理解。

这是你所做的。想象一下这个数组。{5,3,0,4,1,2,6}

按降序排序后,您将得到{6,5,4,3,2,1,0}。通过只从第一项中获取1项,您将获得{6}数组。因为它是有序的,你总是取最大的值。

这是我所做的。我只是简化了一下。

在我按升序排序后,我将得到{0,1,2,3,4,5,6}。因为这是有序的,所以最后一项的值总是最大的。我只会得到最后一项6

因为Take()返回一个序列,您必须使用SelectMany将其展开为单个项目。但是LastOrDefault返回一个项目,所以你必须使用Select直接选择项目。

正如@Ivan Stoev建议的那样,你也可以安全地使用Last。阅读下面的评论