17

配列をキーとして使用するハッシュがあります。配列を変更すると、ハッシュは対応するキーと値を取得できなくなります。

1.9.3p194 :016 > a = [1, 2]
 => [1, 2] 
1.9.3p194 :017 > b = { a => 1 }
 => {[1, 2]=>1} 
1.9.3p194 :018 > b[a]
 => 1 
1.9.3p194 :019 > a.delete_at(1)
 => 2 
1.9.3p194 :020 > a
 => [1] 
1.9.3p194 :021 > b
 => {[1]=>1} 
1.9.3p194 :022 > b[a]
 => nil 
1.9.3p194 :023 > b.keys.include? a
 => true 

私は何を間違っていますか?

更新:わかりました。a.clone を使用することは、この問題に対処する 1 つの方法です。「a」を変更したいが、「a」を使用して対応する値を取得したい場合はどうすればよいですか (「a」はまだキーの 1 つであるため)。

4

5 に答える 5

18

#rehashメソッドはハッシュを再計算するため、キーの変更後に次のことを行います

b.rehash
于 2012-08-29T13:37:37.097 に答える
2

ハッシュは、キー オブジェクトのハッシュ コード ( a.hash) を使用してそれらをグループ化します。多くの場合、ハッシュ コードはオブジェクトの状態に依存します。aこの場合、要素が配列から削除されると、のハッシュ コードが変更されます。キーはすでにハッシュに挿入されているため、a元のハッシュ コードでファイルされます。

これは、ハッシュを印刷すると問題ないように見えても、ainの値を取得できないことを意味します。b

于 2012-08-29T13:04:14.673 に答える
1

a.cloneキーとして使用する必要があります

irb --> a = [1, 2]
==> [1, 2]

irb --> b = { a.clone => 1 }
==> {[1, 2]=>1}

irb --> b[a]
==> 1

irb --> a.delete_at(1)
==> 2

irb --> a
==> [1]

irb --> b
==> {[1, 2]=>1} # STILL UNCHANGED

irb --> b[a]
==> nil # Trivial, since a has changed

irb --> b.keys.include? a
==> false # Trivial, since a has changed

を使用すると、後でa.clone変更してもキーが変更されないことが保証されます。a

于 2012-08-29T11:44:02.917 に答える
1

すでに述べたように、問題は、ハッシュ キーが後で変更するオブジェクトとまったく同じであることです。つまり、キーはプログラムの実行中に変更されます。

これを回避するには、配列のコピーを作成してハッシュ キーとして使用します。

a = [1, 2]
b = { a.clone => 1 }

これで、作業を続行しa、ハッシュ キーをそのままにしておくことができます。

于 2012-08-29T11:52:22.277 に答える