1

-esHashを作成しようとしています。Hash第2レベルのハッシュの値は、デフォルトで0の整数です。私がやろうとしているのは、ハッシュの空のハッシュから始めて、キーが存在しない場合に値を追加するときに、それらのキーを追加する必要があります。デフォルト値で。

単純なHash整数でこれを試してみると、正常に機能します。

irb(main):003:0> h = Hash.new(0)
=> {}
irb(main):004:0> h[1] += 1
=> 1
irb(main):005:0> p h
{1=>1}
=> nil
irb(main):006:0> h.keys.size
=> 1
irb(main):007:0>

h現在、1つのキーと1の値があります。完璧です。

しかし、私のハッシュの値がハッシュである場合、それは機能していないようです:

irb(main):007:0> h = Hash.new(Hash.new(0))
=> {}
irb(main):008:0> h[1][1] += 1
=> 1
irb(main):009:0> p h
{}
=> nil
irb(main):010:0> h.keys.size
=> 0
irb(main):011:0>

何か間違ったことをしているのですか、それともハッシュのデフォルト値をに設定できませんHash.new(0)か?

編集:

以下の回答に基づいて、私は自分が間違っていることを理解することができました。実際、私は自分の考えがどこに間違っているのかを理解することができました。簡単に言うと、呼び出すコードのブロックを指定しない限り、呼び出しをh[1][1]ネストしません。式の値は期待どおりですが、最も内側のハッシュのみが正しく初期化されていました。Hash.newHash.newh[1][1] += 11

上記の例では2次元ハッシュを使用していますが、実際の問題では3次元ハッシュを使用しているため、これを投稿します。

syms[level][exchange][symbol] = count

この解決策は、この問題を抱えている他の人に役立つ可能性があるため、これを私が望むように機能させるコードを次に示します。

irb(main):024:0> syms = Hash.new{|h1,k1| h1[k1] = Hash.new{|h2,k2| h2[k2] = Hash.new(0)}}
=> {}
irb(main):026:0> syms["level1"]["NYSE"]["IBM"] += 1
=> 1
irb(main):027:0> p syms
{"level1"=>{"NYSE"=>{"IBM"=>1}}}
=> nil
irb(main):028:0>
4

2 に答える 2

4

ハッシュを作成するときにデフォルト値を設定する最も一般的な方法は、ブロック引数で Hash#new 関数を使用することです。

h = Hash.new { |h, k| h[k] = Hash.new(0) }

問題は、実行するコードではなく、オブジェクト ポインターにデフォルトを設定していることです。つまり、「外部」ハッシュの欠損値にアクセスするたびに、まったく同じオブジェクトへのポインターが返されます。これを自分で証明するには、次のことを試してください。

>> h = Hash.new(Hash.new(0))
=> {}
>> h[1] === h[2]
=> true

したがって、実際にはハッシュのデフォルト値を設定できますが、そうすると目的が達成されません。h[1][1] をインクリメントすると、h[1] が初期化されていないため、実際にはデフォルトのハッシュ自体が変更されます。

お役に立てれば。

于 2010-08-26T14:39:16.600 に答える
4
h = Hash.new(Hash.new(0))

Hash.new(0) はデフォルトのオブジェクトです。これは、存在しないすべてのキーに対して同じオブジェクトです。キーが存在しない場合にハッシュが返すものです。

h = Hash.new{|h,k| h[k]=Hash.new(0)}

{|h,k| h[k]=Hash.new(0)} がデフォルトの Proc です。キーが存在しない場合に実行され、存在しないキーごとに新しいハッシュ (デフォルトは 0) を作成します。

于 2010-08-26T14:42:38.837 に答える