デフォルトのメソッドがハッシュに対して何をするかを理解したと思いました...
キーが存在しない場合は、デフォルト値を指定します。
irb(main):001:0> a = {}
=> {}
irb(main):002:0> a.default = 4
=> 4
irb(main):003:0> a[8]
=> 4
irb(main):004:0> a[9] += 1
=> 5
irb(main):005:0> a
=> {9=>5}
すべて良い。
しかし、デフォルトを空のリストまたは空のハッシュに設定した場合、all ...での動作がわかりません。
irb(main):001:0> a = {}
=> {}
irb(main):002:0> a.default = []
=> []
irb(main):003:0> a[8] << 9
=> [9] # great!
irb(main):004:0> a
=> {} # ?! would have expected {8=>[9]}
irb(main):005:0> a[8]
=> [9] # awesome!
irb(main):006:0> a[9]
=> [9] # unawesome! shouldn't this be [] ??
|| =演算子を使用した場合と同じ動作を期待/期待していました...
irb(main):001:0> a = {}
=> {}
irb(main):002:0> a[8] ||= []
=> []
irb(main):003:0> a[8] << 9
=> [9]
irb(main):004:0> a
=> {8=>[9]}
irb(main):005:0> a[9]
=> nil
誰かが何が起こっているのか説明できますか?
Hash.default
は、存在しないキーをクエリするときにデフォルト値returnedを設定するために使用されます。コレクション内のエントリは、クエリされたという理由だけで作成されません。
また、default
に設定した値は、オブジェクト(この場合は配列)のインスタンスであるため、これが返されたときに操作できます。
a = {}
a.default = [] # set default to a new empty Array
a[8] << 9 # a[8] doesn't exist, so the Array instance is returned, and 9 appended to it
a.default # => [9]
a[9] # a[9] doesn't exist, so default is returned
これは非常に便利なイディオムです。
(myhash[key] ||= []) << value
ネストすることもできます。
((myhash[key1] ||= {})[key2] ||= []) << value
もう1つの方法は、次のことです。
myhash = Hash.new {|hash,key| hash[key] = []}
しかし、これには重大な副作用があり、キーについてaskingがキーを作成し、has_keyをレンダリングしますか?かなり役に立たないので、私はこの方法を避けます。
これがあなたが探している行動だと思います。これにより、ハッシュ内の新しいキーが配列に自動的に初期化されます。
irb(main):001:0> h = Hash.new{|h, k| h[k] = []}
=> {}
irb(main):002:0> h[1] << "ABC"
=> ["ABC"]
irb(main):003:0> h[3]
=> []
irb(main):004:0> h
=> {1=>["ABC"], 3=>[]}
グレンマクドナルドは言う:
「もう1つの方法は、次のことです。
myhash = Hash.new {| hash、key | hash [key] = []}
しかし、これには重大な副作用があり、キーについて尋ねるとキーが作成され、has_keyがレンダリングされますか?かなり役に立たないので、この方法は避けます。」
それは実際には真実ではないようです。
irb(main):004:0> a = Hash.new {|hash,key| hash[key] = []}
=> {}
irb(main):005:0> a.has_key?(:key)
=> false
irb(main):006:0> a[:key]
=> []
irb(main):007:0> a.has_key?(:key)
=> true
アクセス私が期待するように、キーはそれを作成します。 has_keyを尋ねるだけですか?ではない。
あなたが本当に無限に深いハッシュを持ちたいのなら:
endless = Hash.new { |h, k| h[k] = Hash.new(&h.default_proc) }
endless["deep"]["in"]["here"] = "hello"
もちろん、Glennが上で指摘したように、これを行うと、has_key?常にtrueを返すため、その意味が失われます。これはjbarnetteに感謝します。
irb(main):002:0> a.default = []
=> []
irb(main):003:0> a[8] << 9
=> [9] # great!
このステートメントを使用して、デフォルトを変更しました。新しいアレイを作成して「9」を追加していません。この時点で、代わりにこれを行った場合と同じです。
irb(main):002:0> a.default = [9]
=> [9]
したがって、これを取得するのは当然のことです。
irb(main):006:0> a[9]
=> [9] # unawesome! shouldn't this be [] ??
さらに、「<<」は「9」を配列に追加しました。それはハッシュにそれを追加しませんでした、それはこれを説明します:
irb(main):004:0> a
=> {} # ?! would have expected {8=>[9]}
.defaultを使用する代わりに、プログラムで実行したいことは次のようになります。
# Time to add a new entry to the hash table; this might be
# the first entry for this key..
myhash[key] ||= []
myhash[key] << value