2012-01-21 70 views
2

我會通過本教程:http://tutorials.jumpstartlab.com/projects/jsattend.html排序與零哈希作爲重點

在迭代7,第3步中我們得到排序哈希,稱爲state_data,它具有零作爲重點。所提出的解決方案是:

state_data = state_data.sort_by{|state, counter| state unless state.nil?} 

不幸的是,這是行不通的紅寶石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鍵對我來說似乎不太明智。

更新:從查看您鏈接到的教程,我認爲那裏有很多次優信息。看看下面的一段「紅寶石」,例如:

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) 

雖然紅寶石成語將是:

filename = "output/thanks_#{lastname}_#{firstname}.html" 
File.open(filename, 'w') { |f| f.write(custom_letter) } 

這表明作者在Ruby中似乎不太適合。因此,我不能推薦該教程。

+0

謝謝!信息豐富且完整。 –

+0

@Jacopo:在你的特殊情況下,對我來說簡單的'states.select(&:first).sort + states.reject(&:first)'也可能就足夠了。 –

+1

* * *,即'文件。從教程中得到的新東西甚至不是壞的Ruby,因爲它泄露了一個文件描述符,所以在任何帶有Unix靈感的IO庫(C,C++,Java,Perl,Python,你命名它)的語言中都是壞的。 –