コードには2つの問題があります。最初はh
が空であるとh
キー2
を持っていないので、あなたは、そう何のキーと値をデフォルト値を返さないので、この式は[] << 1 #=> [1]
なるが、[1]
はハッシュに添付されていないh[2]
、h[2] << 1
、たとえば、書くときということですが加えられる。
書く必要があります。h[2] = h[2] << 1
です。その場合、コードはh #=> {3=>[0, 1, 2, 3], 2=>[0, 1, 2, 3], 4=>[0, 1, 2, 3]}
を返します。残念ながら、それはまだ間違っています。これは、コードで2番目の問題を引き起こします。新しく作成したハッシュのデフォルト値を正しく定義していないからです。
h[3].object_id
#=> 70113420279440
h[2].object_id
#=> 70113420279440
h[4].object_id
#=> 70113420279440
あはっは、すべての3つの値が同じオブジェクトであることを
最初のノート! h
にキーk
がない場合、new
の引数[]
はh[k]
によって返されます。問題は、同じ配列がすべてのキーk
に返されるため、最初の新しいキーの空の配列にキーと値のペアを追加してから、2番目のキーと値のペアを追加することですそのと同じ次の新しいキーの配列など。ハッシュの定義方法については、以下を参照してください。
あなたのコードはうまく動作しますが、私は次のように書くことをお勧めします。
ハッシュの
デフォルト値を計算するためにブロックを使用しています
Hash::newの形(すなわち、ハッシュ
h
キー
k
を持っていないとき
h[k]
によって返された値)を使用し
arr = [ [1, 1, 1], [1, 1], [1, 1, 1, 1], [1, 1] ]
arr.each_with_index.with_object(Hash.new {|h,k| h[k]=[]}) { |(a,i),h|
h[a.size] << i }
#=> {3=>[0], 2=>[1, 3], 4=>[2]}
、
か
:
arr.each_with_index.with_object({}) { |(a,i),h| (h[a.size] ||= []) << i }
#=> {3=>[0], 2=>[1, 3], 4=>[2]}
両方のは、以下の効果であります
もう1つの方法は、内側の配列ごとにインデックスを取得した後に配列サイズをグループ化することです(Enumerable#group_by)。
h = arr.each_with_index.group_by { |a,i| a.size }
#=> {3=>[[[1, 1, 1], 0]],
# 2=>[[[1, 1], 1], [[1, 1], 3]],
# 4=>[[[1, 1, 1, 1], 2]]}
h.each_key { |k| h[k] = h[k].map(&:last) }
#=> {3=>[0], 2=>[1, 3], 4=>[2]}
1発現h[2] = h[2] << 1
は=
の左側にh[2]
は、デフォルト値を返さない理由である、方法Hash#[]=とHash#[]を使用しています。代わりに、この式はh[2] ||= [] << 1
と書くことができます。
ああを与えるだろう。私は 'arr.with_object'を最初に試みて失敗しました。 – ybakos
私の答えで使用したコードの臭いを避けて、ブロックからハッシュを宣言する、非常に便利な '#with_object'。もう一度感謝します。あなたのようなマスターから学ぶチャンスがあることは特権です。 –
@ybakos 'with_object'はEnumeratorオブジェクトでのみ機能します。あるいは、Arrayクラスに 'with_object'メソッドが定義されていないと言うこともできます。 –