5

任意の名前の文字列のカウントを追跡してから、カウントをゼロにリセットしたいと思います。私の考えは次のことをすることでした:

reset_hash={"string1"=>0,"string2"=>0,"string3"=>0}
=> {"string1"=>0, "string2"=>0, "string3"=>0} 

new_hash = reset_hash
=> {"string1"=>0, "string2"=>0, "string3"=>0} 

new_hash["string1"]=1
new_hash["string3"]=1
new_hash
=> {"string1"=>1, "string2"=>0, "string3"=>1}

..。

ここで、new_hashをreset_hashにリセットします。

new_hash = reset_hash
=> {"string1"=>1, "string2"=>0, "string3"=>1}
reset_hash
=> {"string1"=>1, "string2"=>0, "string3"=>1} 

ここで何が起こっているのですか?reset_hashは実際にはnew_hashに設定されているようですが、これは私が望んでいたものとは逆です。目的の動作を実装するにはどうすればよいですか?

4

4 に答える 4

5

オブジェクトを指す変数がある場合、実際にはオブジェクトへの参照があります。aとbの両方がハッシュ{1=>3、 "foo" => 54}を指している場合、aまたはbを変更するともう一方が変更されます。

ただし、2つの方法を組み合わせて使用​​して、必要なものを作成できます。

ハッシュのデフォルト値:

new_hash = Hash.new(0)

これにより、未使用の値のデフォルト値は0になります。

new_hash["eggs"]  # -> 0

次に、カウントを追加できます。

new_hash["string1"] += 1 # => 1

終わったら電話するだけ

new_hash.clear # => {}

ハッシュはリセットされますが、新しいアクセスはデフォルトで0になります。

デフォルト値を数値以外のオブジェクトのタイプに設定すると、上記の参照の問題全体が原因で変更できる場合があることに注意してください。

irb(main):031:0> b = Hash.new("Foo") #=> {}
irb(main):032:0> b[3] #=> "Foo"
irb(main):033:0> b[33] #=> "Foo"
irb(main):034:0> b[33].upcase! #=> "FOO"
irb(main):035:0> b[3] # => "FOO"

これを回避するには、ハッシュにブロックを渡すことができます。

h = Hash.new {|hash, key| hash[key] = "new default value"}

これにより、キーに毎回新しいオブジェクトが作成されるため、1つに変更しても波及しません。

d = Hash.new{ |hash,key| hash[key] = "string"} #=> {}
d[3] # => "string"
d[3].upcase! #=> "STRING"
d[5] #=> "string"
于 2012-07-16T20:25:24.310 に答える
5

他の人が述べたように、あなたはクローンを使わなければなりません。タスクは次のようになります。

reset_hash={"string1"=>0,"string2"=>0,"string3"=>0}
new_hash = reset_hash.clone

new_hash["string1"]=1
new_hash["string3"]=1
new_hash

new_hash = reset_hash.clone
reset_hash
于 2012-07-16T20:28:36.237 に答える
2

単一のハッシュを変更しています。

両方の変数が同じハッシュを参照しています。ハッシュ内のアイテムを変更すると、両方の参照がその変更を反映します。これは、同じハッシュインスタンスであるためです。

おそらく、最初にハッシュをコピーしたいですか?そうした場合、複雑なオブジェクトを含むハッシュがある場合は、浅いコピーと深いコピー/クローン作成も調査する必要があります。

于 2012-07-16T20:16:35.843 に答える
1

コピーを作成するには、クローンを使用する必要があります。

https://stackoverflow.com/a/4157438/1118101を参照してください

それ以外の場合は、コンテンツをコピーするのではなく、同じハッシュに対して2つの「ポインター」を作成するだけです。

次に、replaceを使用して、複製されたコンテンツを既存のハッシュにコピーして戻します。

于 2012-07-16T20:17:26.157 に答える