Хорошо ли использовать fixnums в качестве ключей в хеше Ruby?

Я создаю хэш для представления нескольких записей в базе данных MySQL. Хэш-ключи соответствуют полям идентификатора базы данных, а хэш-значения соответствуют полям имени базы данных.

Что лучше и почему?

  1. Множество

    Это работает, но Ruby кажется неэффективным с разреженными массивами, потому что кажется, что есть дополнительные накладные расходы на установку значений всех промежуточных индексов tp nil.

    fruits = []
    fruits[23] = "apple"
    fruits[109] = "orange"
    # ...
    fruits[23429] = "banana"
    
  2. Хэш с fixnum в качестве ключей

    Мне это нравится больше всего, но я всегда читал, что лучше всего использовать символы в качестве ключей в хеше. Так же хорошо использовать fixnums как ключи в хэше? Я не уверен, так ли это, но я думаю, что 34.hash из-за природы fixnums, то есть 34.equal? 34 верно, тогда как "hi".equal? "hi" ложно.

    fruits = {
      23 => "apple",
      109 => "orange",
      # ...
      23429 => "banana"
    }
    
  3. Хэш с интернированными строковыми представлениями fixnums в качестве ключей

    Преобразовывая фиксированные числа в строки, а затем в символы, я могу использовать символы в качестве ключей. Однако это преобразование раздражает, и кто-то однажды сказал мне, что интернирование строк неэффективно. Это так? Они просто кажутся мне уродливыми.

    fruits = {
      :"23" => "apple",
      :"109" => "orange",
      # ...
      :"23429" => "banana"
    }
    
  4. Хэш с символами в качестве ключей

    Я могу получить более красивые символы (а также использовать новый синтаксис хэшей Ruby 1.9), добавляя к каждой клавише префикс альфа-символа, но это решение также требует преобразования.

    fruits = {
      i23: "apple",
      i109: "orange",
      # ...
      i23429: "banana"
    }
    

person ma11hew28    schedule 30.03.2011    source источник
comment
Я действительно не понимаю причин использования только символов в качестве ключей для хэша. Есть ли у вас какие-либо ссылки, которые дают хорошее объяснение, почему это может быть так?   -  person Vadim    schedule 30.03.2011
comment
Этот сообщение в блоге о понимании символов Ruby дает хороший объяснение, почему и когда использовать символы над строками. И это сообщение в блоге рекомендует рубиновый символ как отличный выбор для хеш-ключа. Но как насчет фикснумов? Разве они не одинаково хороши как символы для использования в качестве хеш-ключей? Я утверждаю, что они есть.   -  person ma11hew28    schedule 30.03.2011
comment
Спасибо, если основная проблема, которую решают символы в хэшах, это управление памятью, то я думаю, что @DigitalRoss на 100% прав.   -  person Vadim    schedule 30.03.2011


Ответы (2)


Насколько я знаю, причина в том, что symbol.hash является константой, поэтому вызов hash для символа является простым поиском свойства и довольно быстрым; символы оптимизированы для этого конкретного использования. Хэш-значение для строки необходимо вычислить, поэтому вызов hash для строки требует реальной работы, а строки не кэшируют свои хеш-значения. Значение hash для Fixnum, по-видимому, вычисляется с помощью простого битового искажения внутреннего идентификатора объекта Fixnum (константа), поэтому оно также должно быть быстрым. Не считайте это авторитетным, я только что просмотрел исходный код 1.9.2, но вряд ли я эксперт по внутренностям Ruby.

Тем не менее, я бы использовал Fixnums в качестве хеш-ключей. Это дает вам естественное представление разреженного массива, которое также эффективно с точки зрения памяти. Любые различия в скорости, вероятно, будут неуместным шумом. Итак, используйте самый ясный подход и беспокойтесь об оптимизации, когда есть реальная проблема со скоростью.

person mu is too short    schedule 30.03.2011

Мое предложение: используйте Hash с Fixnum ключами.

Как вы говорите, это позволит разреженный объект. Существуют специальные оптимизации скорости и памяти, которые применяются к Fixnums. Они сравниваются, как и ожидалось, и конвертируются во все. Это должно быть быстрее и проще, чем символы, и у вас не будет странностей интернирования строк, которые обычно не могут быть проанализированы.

person DigitalRoss    schedule 30.03.2011