2012-01-23 38 views
3

我正在瀏覽教程Bastards Book of Ruby,並且我無法理解函數sort_by的工作原理。這裏的運動:試圖瞭解sort_by函數如何在Ruby中工作

練習:由下式給出了表示「姓」形式的名稱,使用sort_by和分裂,返回按姓氏排序的字符串數組的數組姓氏

排序名稱。爲了簡單起見,假設每個名稱只包含兩個用空格分隔的詞(即只有「John Doe」而不是「Mary Jo Doe」)。

names = ["John Smith", "Dan Boone", "Jennifer Jane", "Charles Lindy", "Jennifer Eight", "Rob Roy"] 

而這裏的解決

names = ["John Smith", "Dan Boone", "Jennifer Jane", "Charles Lindy", "Jennifer Eight", "Rob Roy"] 
sorted_names = names.sort_by do |name| 
    name.split(" ").reverse.join.upcase 
end 

puts sorted_names.join('; ') 
# output=> Dan Boone; Jennifer Eight; Jennifer Jane; Charles Lindy; Rob Roy; John Smith 

然而,當我運行代碼

sorted_names = names.sort_by do |name| 
    puts name.split(" ").reverse.join.upcase 
end 

我得到的輸出:

SMITHJOHN 
BOONEDAN 
JANEJENNIFER 
LINDYCHARLES 
EIGHTJENNIFER 
ROYROB 

這比從puts sorted_names.join('; ')

輸出相當不同我認爲該方法實際上是操作數據(因此name.split(" ").reverse.join.upcase),然後將其保存到新的數組sorted_names。但顯然不是。所以,我的問題是有人可以解釋爲什麼這種方法是這樣的。我對Ruby比較陌生,我試圖通過Ruby docs尋找解釋,但找不到一個。我覺得我沒有理解Ruby中的一個重要概念,並希望得到任何幫助或見解。

回答

4

sort_by是一種像這樣做:

a.map {|item| [f(item), item]}.sort.map {|key, item| item} 

也就是說,sort_by塊用於計算針對陣列中的每個值的排序鍵,然後這些鍵進行排序,然後將這些鍵被映射回原始值。

所以你看到的是那些鍵,在它們用於排序之前。除了注意到的排位,投入回報零,所以通過檢查你已經打破了功能的關鍵!

+0

這是有道理的。我最初對新數組的輸出感到驚訝,期望得到高位的名字,但是現在我知道'sort_by'方法只是使鍵最終被排序。感謝您的洞察力 – Abundnce10

4

#sort_by期望您返回一個值進行排序。事實上,你有puts其中return應該是導致#sort_by爲每個元素返回nil,這防止發生任何排序。

0

不知道這會在這種情況下幫助,但tap是非常方便的事情閒逛而不會干擾控制流程:

sorted_names = names.sort_by do |name| 
    name.split(" ").reverse.join.upcase.tap { |str| puts str } 
end