Ruby: Почему одни и те же строки имеют разные хэш-коды? - PullRequest
1 голос
/ 22 апреля 2010
test = 'a'
test2 = '@a'.slice(0)
test3 = '@a'[1]

puts test.hash
puts test2.hash
puts test3.hash

Вывод:

100
64
97

Это ошибка или я неправильно понимаю, как работает метод хеширования?Есть ли способ это исправить?

Ответы [ 3 ]

3 голосов
/ 22 апреля 2010

Результаты этих выражений не являются одинаковыми данными.Целые числа Ruby 1.8 содержат номера символов для индексации одного символа.Это было изменено в Ruby 1.9, но slice(0) возвращает первый символ строки '@', а не 'a'.

В Ruby 1.8 (используя irb):

irb(main):001:0> test = 'a'
=> "a"
irb(main):002:0> test2 = '@a'.slice(0)
=> 64
irb(main):003:0> test3 = '@a'[1]
=> 97
irb(main):004:0> test.hash
=> 100
irb(main):005:0> test2.hash
=> 129
irb(main):006:0> test3.hash
=> 195

В Ruby 1.9.1:

irb(main):001:0> test = 'a'
=> "a"
irb(main):002:0> test2 = '@a'.slice(0)
=> "@"
irb(main):003:0> test3 = '@a'[1]
=> "a"
irb(main):004:0> test.hash
=> 1365935838
irb(main):005:0> test2.hash
=> 347394336
irb(main):006:0> test3.hash
=> 1365935838
2 голосов
/ 22 апреля 2010

Причина в том, что каждая переменная относится к разному объекту со своим уникальным хеш-кодом!Переменная test - это строка «a», test2 - это целое число 64 (номер символа «@»), а test3 - это целое число 97 («a»).Сюрпризом, вероятно, является то, что в Ruby элементы строк являются целыми числами, а не строками или символами.

1 голос
/ 22 апреля 2010

Как указывает maerics, если вы не определили свой собственный метод хеширования для класса, который вы используете, хеш может быть просто на самом объекте, а не на его содержимом. Тем не менее, вы можете (и должны) определить свой собственный хеш-метод для любого класса, в котором вы определяете метод equals.

В Ruby класс String уже делает это для вас:

irb(main):001:0> test="a"
=> "a"
irb(main):002:0> test2="a"
=> "a"
irb(main):003:0> test.hash
=> 100
irb(main):004:0> test2.hash
=> 100
irb(main):005:0> test2[0]=test.slice(0)
=> 97
irb(main):006:0> test2
=> "a"
irb(main):007:0> test2.hash
=> 100

Я не нашел эквивалентного текста для Ruby, но эта страница на Java предоставляет отличный алгоритм для генерации собственного хеш-кода, который нетрудно скопировать для Ruby: http://www.javapractices.com/topic/TopicAction.do?Id=28

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...