请问为什么第三个查询比前两个慢了几个数量级,明明不应该比按顺序执行前两个查询的时间长吗?
var data = Enumerable.Range(0, 10000).Select(x => new { Index = x, Value = x + " is the magic number"}).ToList();
var test1 = data.Select(x => new { Original = x, Match = data.Single(y => y.Value == x.Value) }).Take(1).Dump();
var test2 = data.Select(x => new { Original = x, Match = data.Single(z => z.Index == x.Index) }).Take(1).Dump();
var test3 = data.Select(x => new { Original = x, Match = data.Single(z => z.Index == data.Single(y => y.Value == x.Value).Index) }).Take(1).Dump();
编辑:我已经在原始数据生成中添加了.ToList(),因为我不希望重复生成数据影响问题。
顺便说一下,我只是想弄清楚为什么这段代码如此缓慢,并不是寻找更快的替代方案,除非它能阐明问题。我本以为如果Linq是惰性求值的,而我只需要查找第一个项目(Take(1)),那么test3的:
data.Select(x => new { Original = x, Match = data.Single(z => z.Index == data.Single(y => y.Value == x.Value).Index) }).Take(1);
可以简化为:
data.Select(x => new { Original = x, Match = data.Single(z => z.Index == 1) }).Take(1)
在数据的第一项通过内部Single()函数进行一次完整扫描后成功匹配,留下剩余的Single()函数需要对数据再进行一次扫描。因此,仍然是O(N)时间复杂度。
显然,这种方式处理数据更加冗长,但我不太理解其如何或为何。
顺便提一下,Test3运行需要几秒钟的时间,因此如果你的答案中出现了10^16这个数字,我们可以安全地假定你在某个地方犯了错误。
ToList()
替换Dump()
,并在没有 LINQPad 的情况下观察到减速。 - Jay Bazuzi