2010-11-09 51 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