2010-11-09 25 views
0

在Ruby中,如果我要循环集合,Ruby会评估枚举集合多少次?Ruby评估循环的枚举集合多少次?

具体来说,我想对一个集合进行排序,并遍历排序后的集合。因为我已经没有必要保持分类收集副本的时候,我想我会只写循环为:

for item in @items.sort{ |a,b| b.created_at <=> a.created_at } do 
    #do some stuff 
end 

然而,各具特色该代码可爱一点我开始怀疑后,有多少次我可能实际上是调用排序。

上面的行确实只会收集一次吗?或者,Ruby最终会对集合中的每个项目进行N次排序?

+0

@ sepp2k在他的第二个例子中展示了循环集合的更习惯的'@ items.sort ...'形式。我认为我没有看到任何人在我读过的所有源代码中使用Ruby中的for/loop。我不知道为什么,但也许它只是Ruby方式。 – 2010-11-09 04:31:24

+0

@Greg,谢谢。我仍然在学习'Ruby的方式',而Ruby的众多循环构造让我惊叹不已。我从来没有见过有太多不同方式来迭代的语言。 – 2010-11-09 04:37:20

+0

Ruby是我用过的最自由的语言;我听说它几次被称为禅宗式的。我认为这不适合每个人,但对于那些适合自己的大脑的人来说,它非常优雅。 – 2010-11-09 05:00:48

回答

1

您打给sort一次。

除了范围界定的差异,

for x in xs do 
    some_stuff 
end 

相同

xs.each do |x| 
    some_stuff 
end 

当然,当你foo.bar(baz)foo被计算一次,无论什么bar一样。

+1

在第一个例子中,for循环结束后,'x'将保留其值,第二个例子中的情况也是如此。 – 2010-11-09 03:14:27

+0

@EdSwangren:这就是我所说的“范围差异”。 – sepp2k 2010-11-09 03:15:07

+0

谢谢你澄清。阅读@ sepp2k答案后,我很好奇他们有什么不同的范围。其实我正在阅读其他一些SO问题,看看我能否找到答案。谢谢你们,你们实际上回答了我的两个问题,我甚至都没有想过要问.each循环:-D – 2010-11-09 03:17:29

1

这相当于对整个集合进行一次排序,然后迭代一次。

等同于:

@items.sort{ |a,b| b.created_at <=> a.created_at }.each do |item| 
    # do some stuff 
end 
0

即使是更清洁和更快:

@items.sort_by {|a| a.created_at}.reverse 

你应该几乎总是使用sort_by,而不是如果你可以(而且你总是能)sort,因为它每个项目仅评估一次排序键功能。它可以让你写一半的比较代码!

+0

小心使用'sort_by'而不是'sort'。 Sort_by默认有更多的开销,如果你做了一个简单的比较,开销会压倒可能的加速,导致排序时间明显变慢。 'sort_by'适用于在进行昂贵的查找或计算以查找用于排序的实际关键字时使用,并且会因中间结果的缓存而获得。我昨天在1.9上做了一些基准测试。2,'sort'比正常比较的'sort_by'速度快8倍。这会花费相当昂贵的查找来加快“sort_by”的速度。 – 2010-11-09 18:12:01

+0

你的实际比较是什么?我刚刚计时'sort_by {| x | x [:key]}'vs'sort {| x,y | x [:key] <=> y [:key]}',它的大小非常简单,sort_by的速度是排序的两倍。但那是1.9.1,所以还有另一个变量。 – 2010-11-09 19:15:23