使用 Linq 获取列表的最大值?

时间:2021-05-12 21:43:49

标签: c# linq

我有以下列表:

List<Decimal?> values = new List<Decimal?> { 3, null, 2, 1, 4, 3 };

我需要创建一个新列表,其中包含每个项目与前两个项目之间的最大值,因此:

List<Decimal?> maximums = new List<Decimal?> { 3, 2, 4, 4 };

3 = Maximum of { 3, null, 2 }

2 = Maximum of { null, 2, 1 }

4 = Maximum of { 2, 1, 4 }

4 = Maximum of { 1, 4, 3 }

我的想法是有一个循环,并在每次迭代中执行:

for (int i = 2; i < values.Count(); i++) {
  Decimal? maximum = values.Skip(i).Take(3).Max();
  maximums.Add(maximum);
} 

有没有办法只使用 Linq 来做到这一点?

2 个答案:

答案 0 :(得分:4)

我不确定您和其他答案为什么会先执行 Skip(2)。根据 3,2,4,4 的输入所需的 3,null,2,1,4,3 输出,您不会得到正确的结果。如果你真的想跳过2,那么修改下面的代码。

您要查找的内容通常被认为是 sliding window

如果你同意它,有一个 Morelinq 方法被适当地调用,Window() 将产生一个序列序列,每个序列的长度都需要。

您可以像这样将其应用于您的问题

var values = new List<decimal?> { 3, null, 2, 1, 4, 3 };
var maximums = values.Window(3).Select(x => x.Max()).ToList();

对于长度不超过 3 的每个子序列,我们选择最大值。这会产生您想要的结果:3,2,4,4

Window() 方法缓冲每个序列,但整体流式传输结果。没有使用 Skip(),因此您不会陷入将源扫描到每个索引的陷阱,从而提高效率。

如果你不想下载包,你可以自己滚动,而不是产生窗口序列,直接从缓冲序列中产生最大值。

答案 1 :(得分:0)

当然 - 只需使用 Skip(2) 来模拟您的循环:

values.Skip(2).Select((x,i) => values.Skip(i).Take(3).Max())
相关问题