gpt4 book ai didi

c# - OrderBy 的效率和延迟执行

转载 作者:行者123 更新时间:2023-11-30 22:14:56 25 4
gpt4 key购买 nike

我有一个包含日期和值的对象列表。每个日期有一个对象,过去几个月的每个日期都有一个对象。我正在查找值更改为最新值的日期。

这是我的意思的一个例子:

<datevalue>
<date>8-9</date>
<value>5</value>
</datevalue>
<datevalue>
<date>8-10</date>
<value>6</value>
</datevalue>
<datevalue>
<date>8-11</date>
<value>5</value>
</datevalue>
<datevalue>
<date>8-12</date>
<value>5</value>
</datevalue>
<datevalue>
<date>8-13</date>
<value>5</value>
</datevalue>

在上面的示例中,当前值为 5,因为它是最近日期 8-13 的值。我想返回 8-11 日期值对象,因为它是值更改为最新值的日期。我不想要 8-9 值,因为即使它是当前值的最早一天,该值在该日期之后也发生了变化。

这是我第一次尝试解决这个问题:

DateValue FindMostRecentValueChange(List<DateValue> dateValues)
{
var currentValue = dateValues
.OrderByDesc(d => d.date)
.Select(d => d.value)
.First();
var mostRecentChange = dateValues
.OrderByDesc(d => d.date)
.TakeWhile(d => d.value = currentValue)
.Last();
return mostRecentChange;
}

这行得通。但是,有人向我指出,我正在为这两个操作重复 OrderByDesc。考虑到 OrderByDesc 可能是一项昂贵的操作,我不想做两次。因此我做了一个改变:

DateValue FindMostRecentValueChange(List<DateValue> dateValues)
{
var orderedDateValues = dateValues.OrderByDesc(d => d.date);
var currentValue = orderedDateValues;
.Select(d => d.value)
.First();
var mostRecentChange = orderedDateValues
.TakeWhile(d => d.value = currentValue)
.Last();
return mostRecentChange;
}

现在我只调用一次 OrderByDesc。这是一个进步,对吧?好吧,也许不是。 OrderByDesc 是延迟执行。

据我了解,这意味着实际的排序在您向它请求值之前不会完成。因此,当您在查找 currentValue 时调用 First() 时执行 OrderByDesc,然后在查找 mostRecentChange 时调用 Last() 时再次执行它。那么这是否意味着我仍在执行两次 OrderByDesc?

我是否正确解释了延迟执行的运作方式?我希望编译器能够识别这种情况并在幕后对其进行优化,以便只调用一次执行,但我找不到任何信息来支持这一理论。你能帮我想想优化这个解决方案的最佳方法吗?

最佳答案

So does that mean that I'm still executing OrderByDesc twice?

是的,这是正确的。

I would hope that the compiler would recognize this scenario and optimize it behind the scenes so that the execution is only called once, but I cannot find any information to support this theory.

它不能,因为这会在几个关键方面改变预期的功能。

  1. 如果基础数据发生变化,则应在再次迭代序列时反射(reflect)这些变化。如果您在第一个查询和第二个查询之间向 dateValues 添加了一个新项目,它应该在第二个查询中。如果你删除了一个项目,它不应该在那里,等等。

  2. 要获得您想要的东西,它需要将所有项目存储在某种集合中,即使在第一个消费者“完成”它们之后也是如此。这是不可取的。这里的想法是您可以流式传输数据,一旦您处理完一个项目,您就“完成”了它,不需要将它保存在内存中。如果您没有足够的内存来保留查询中的所有项目以供后续运行,该怎么办?

Can you help me wrap my head around the best way to optimize this solution?

这很简单。只需用查询结果填充数据结构。最简单的方法是将它们全部放在一个列表中。在查询末尾添加一个 ToList 调用,它将对其求值一次,然后生成的列表可以迭代多次而不会产生负面影响。由于此解决方案在需要此类语义时非常容易获得,而延迟执行的语义更难获得,尽管更强大,他们选择不将 LINQ 基于物化集合。

关于c# - OrderBy 的效率和延迟执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18217149/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com