2011-10-20 203 views
2

我有一個這樣的字符串,紅寶石字符串散列轉換

str = "[email protected], [email protected], [email protected], [email protected]"

我想知道如何給定的字符串轉換爲哈希值。 (即我的實際要求是,有多少個值(在@符號之前)有m,n和p,我不想計數,我需要一個確切的值)。輸出會是這樣更好,

{"m" => ["xx", "zz"], "n" => ["yy"], "p" => ["uu"]}

可以幫助我的任何人嗎?一個IRB會議

回答

14

直接拷貝/過去:一個新手:)

str = "[email protected], [email protected], [email protected], [email protected]" 
h = {} 
str.split(",").each do |x| 
    v,k = x.split('@') 
    h[k] ||= [] 
    h[k].push(v) 
end 

p h 
+0

非常感謝@邁克爾。這是我的期望。再一次,我對注射方法的力量感到興奮。可以,你可以解釋這部分「..inject(Hash.new {| h,k | h [k] = []})..」?這有助於提高自己。 –

+0

很高興幫助! :-)如果您的問題得到了充分解答,請接受其他人知道的問題。 –

+0

當然,我正在使用'Hash.new'的塊形式(請參閱文檔)注入一個具有空數組作爲默認值的散列。 –

4

簡單的代碼:

grouped = str.split(", ").group_by { |s| s.split("@")[1] } 
Hash[grouped.map { |d, emails| [d, emails.map { |s| s.split("@")[0] }] }] 

#=> {"m"=>["xx", "zz"], "n"=>["yy"], "p"=>["uu"]} 

像往常一樣,解決的辦法是如果你求助於Facets很酷的抽象(不需要安裝整個庫,只需複製t他具體方法可將擴展模塊):

require 'facets' 
str.split(", ").map_by { |s| s.split("@", 2).reverse } 
#=> {"m"=>["xx", "zz"], "n"=>["yy"], "p"=>["uu"]} 

Facets#map_by = group_by + map

2

FP風格

>> str.split(/, /).inject(Hash.new{|h,k|h[k]=[]}) do |h, s| 
.. v,k = s.split(/@/) 
.. h[k] << v 
.. h 
.. end 
=> {"p"=>["uu"], "m"=>["xx", "zz"], "n"=>["yy"]} 
+0

摺疊(並因此'注入')功能足夠你嗎? ;-) –

+0

我認爲我更喜歡這個,沒有其他原因,它不涉及保持臨時變量的狀態。 – d11wtq

+0

@Michael。我們稱之爲「另一種FP式回答」。但是,請注意,「h [k] << v」幾乎不起作用:-p此外,典型的FP建議是:當手邊還有其他抽象時,不要求助於摺疊(因爲我們可能可以編寫幾乎所有可枚舉的抽象使用摺疊:map/select/group_by/partition/max/min/...)。 – tokland