2012-01-23 35 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