我正在阅读本教程:http://tutorials.jumpstartlab.com/projects/jsattend.html
在迭代7,第3步中,我们对一个名为state_data的哈希进行排序,该哈希值为nil。建议的解决方案是:
state_data = state_data.sort_by{|state, counter| state unless state.nil?}
不幸的是,这不适用于ruby 1.9.2p290(2011-07-09修订版32553)[x86_64-darwin11.0.0]。例如:
~% irb
>> things = { nil => "a", 2 => "b", 3 => "c" }
>> things.sort_by { |k, v| k unless k.nil? }
ArgumentError: comparison of NilClass with 2 failed
from (irb):6:in `sort_by'
from (irb):6
from /Users/jacopo/.rvm/rubies/ruby-1.9.2-p290/bin/irb:16:in `<main>'
同样如下:
>> things.sort_by { |k, v| k if k }
ArgumentError: comparison of NilClass with 2 failed
from (irb):3:in `sort_by'
from (irb):3
from /Users/jacopo/.rvm/rubies/ruby-1.9.2-p290/bin/irb:16:in `<main>'
在教程的情况下,由于它是对状态双字母代码进行排序,因此可能的解决方案是:
state_data = state_data.sort_by{|state, counter| state.nil? ? "ZZ" : state }
这显然是一个黑客攻击。
Ruby处理这个问题的方法是什么?
答案 0 :(得分:9)
该行
state_data.sort_by { |state, counter| state unless state.nil? }
实际上等同于简单的state_data.sort
,因为(state unless state.nil?) == state
无论如何都是如此。你可以做的是从nil
键中分离正确的键,只对前者进行排序:
state_data.select(&:first).sort + state_data.reject(&:first)
在更一般的情况下,您还可以定义这样的自定义比较函数:
def compare(a, b)
return a.object_id <=> b.object_id unless a || b
return -1 unless b
return 1 unless a
a <=> b
end
state_data.sort { |a, b| compare(a.first, b.first) }
通过快速查看,您会发现它非常丑陋。实际上,您应该在此重新考虑您对数据结构的选择。 nil
键对我来说似乎不太合理。
更新:通过查看您链接的教程,我认为其中有很多次优信息。看一下下面的“Ruby”,例如:
ranks = state_data.sort_by{|state, counter| counter}.collect{|state, counter| state}.reverse
state_data = state_data.sort_by{|state, counter| state}
state_data.each do |state, counter|
puts "#{state}:\t#{counter}\t(#{ranks.index(state) + 1})"
end
你可以写得更干净,得到相同的结果:
rank = state_data.sort_by(&:last)
state_data.sort.each do |data|
puts "%s:\t%d\t(%d)" % [*data, rank.index(data) + 1]
end
作者还推荐了像
这样的代码filename = "output/thanks_#{lastname}_#{firstname}.html"
output = File.new(filename, "w")
output.write(custom_letter)
而Ruby的习语是:
filename = "output/thanks_#{lastname}_#{firstname}.html"
File.open(filename, 'w') { |f| f.write(custom_letter) }
这表明作者在Ruby中似乎不太合适。因此,我不推荐该教程。