我有这行C#代码:
datavals
.GroupBy(x => new { x.ElementID, x.OutputTableCode})
.SelectMany(x => x
.OrderByDescending(y => y.Sequence)
.Take(1))
.ToList<TransactionValue<string>>();
我们的想法是按照ElementID
和OutputTableCode
对列表中的项目进行分组,然后根据降序排序对每个组进行排序,并且每个组只返回一个项目。 (这实际上是在一个return语句中,因此修改后的列表将返回给调用函数。)
我的问题是,这会返回具有最大序列的项目,还是不一定是这种情况?在我的测试示例中,确实如此,但不确定它是否有保证。
如果它不一定会返回每个组中具有最大序列的项目,我该如何更改查询呢?
答案 0 :(得分:1)
如果序列为空,它将始终返回序列的最大值或空序列。
我们现在无法知道序列的顺序是什么,所以如果我们通过desc命令 - 我们将得到序列,它由desc排序(最大值 - 第一,最小值 - 最后)。执行.Take(1)
等于执行.FirstOrDefault()
,因此我们将获得序列的最大值。
如果您怀疑.Take()
,可以随时使用.FirstOrDefault()
或.First()
来检索序列的第一个值。
如果您只想获得最大值,可以使用linq .Max()
,您可以在其中设置comparer属性,例如.Max(x => x.Sequence)
答案 1 :(得分:1)
是的,您的代码将返回每个组中包含最大序列的项目。
这是一个解释,可以让您更好地理解您的代码:
{ x.ElementID, x.OutputTableCode}
组合。Sequence
Take()
x ,每组中Sequence
值最高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
。阅读下面的评论