Linq - OrderByDescending和Take(1),它会返回最大项吗?

时间:2015-10-08 04:44:39

标签: c# linq

我有这行C#代码:

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

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

我的问题是,这会返回具有最大序列的项目,还是不一定是这种情况?在我的测试示例中,确实如此,但不确定它是否有保证。

如果它不一定会返回每个组中具有最大序列的项目,我该如何更改查询呢?

3 个答案:

答案 0 :(得分:1)

如果序列为空,它将始终返回序列的最大值或空序列。

我们现在无法知道序列的顺序是什么,所以如果我们通过desc命令 - 我们将得到序列,它由desc排序(最大值 - 第一,最小值 - 最后)。执行.Take(1)等于执行.FirstOrDefault(),因此我们将获得序列的最大值。

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

如果您只想获得最大值,可以使用linq .Max(),您可以在其中设置comparer属性,例如.Max(x => x.Sequence)

答案 1 :(得分:1)

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

这是一个解释,可以让您更好地理解您的代码:

  • GroupBy 只会对项目进行分组。分组将在{ x.ElementID, x.OutputTableCode}组合。
  • 然后, SelectMany 调用将:
    • 首先,按Sequence
    • 的降序对每个组进行排序
    • 然后,Take() x ,每组中Sequence值最高
  • 最后, ToList 只会将每个组的选定 x 作为List<TransactionValue<string>>

答案 2 :(得分:0)

简化使用OrderBy并使用LastOrDefault获取最后一项。您也必须使用SelectMany

代替Select
   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}。从第一项开始只拿一件你会获得{6}的数组。因为它的订购总是占据最大价值。

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

在我通过提升命令后,我会得到{0,1,2,3,4,5,6}。因为这是订购总是最后一项具有最大价值。只是生病得到最后一项6

因为Take()返回序列,您必须使用SelectMany将其解包为单个项目。但LastOrDefault会返回单个项目,因此您必须使用Select直接选择该项目。

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