2012-07-21 14 views
10

私は次のルビコードを試しました。私は、これらの長さの単語に単語長のハッシュを返すと考えました。代わりに空です。私はruby​​ add to array value

map = Hash.new 
strings = ["abc","def","four","five"] 
strings.each do |word| 
    map[word.length] ||= [] 
    map[word.length] << word 
end 

にそれを変更した場合

map = Hash.new(Array.new)  
strings = ["abc","def","four","five"] 
strings.each do |word| 
    map[word.length] << word 
end 

はしかし、それは作業を行います。

最初のバージョンでは、デフォルト値が空の配列であるハッシュを作成するだけではありませんか?この場合、なぜ2つのブロックが異なる値を与えるのか分かりません。

+0

これは奇妙です。最初の例では、 'map = Hash.new {| h、k | h [k] = []} ' –

答えて

21

問題は、実際にはハッシュキーに何も割り当てておらず、<<演算子を使用してデフォルト値の既存の内容を変更しているということです。ハッシュキーには何も割り当てないので、追加されません。

h = Hash.new [] 
p h[0]   # [] 
h[0] << "Hello" 
p h    # {} 
p h[0]   # ["Hello"] 
p h[1]   # ["Hello"] 

同じArrayオブジェクトは、デフォルト値として維持されるので、これは次のとおりです。実際には、デフォルト値が変更さ1でわかります。それはあまり効率的かもしれないが、あなたは、+演算子を使って、それを修正することができます:

map = Hash.new [] 
strings = ["abc", "def", "four", "five"] 

strings.each do |word| 
    map[word.length] += [word] 
end 

そして予想通り、今では動作します。いずれの場合においても

+0

お世話になったよ、ありがとう!しかし、 '+ ='の後の 'word 'を' [word] 'のように配列に変更するまでこれは私のためには役に立たなかった – Subtletree

2

最初のバージョンが実際に意味することは、デフォルト値がの1つだけです。アレイです。 2番目の例では、新しい配列がまだ存在しない場合は明示的に作成します。

これは、さらにclarifyに読まれたように見えます。

+0

ああ、そうです。それは理にかなっている。 –

11

、あなたはEnumerable#group_byを使用する必要があります。

["abc", "def", "four", "five"].group_by(&:length) 
#=> {3=>["abc", "def"], 4=>["four", "five"]} 
+0

ありがとう。私はまだルビーを学んでいるので、イディオムを学ぶことが役に立ちます。 –

+0

華麗な、ありがとう! – Johnsyweb