Хорошо ли использовать фиксированные значения в качестве ключей в хэше Ruby? - PullRequest
2 голосов
/ 30 марта 2011

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

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

  1. Массив

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

    fruits = []
    fruits[23] = "apple"
    fruits[109] = "orange"
    # ...
    fruits[23429] = "banana"
    
  2. Хеш с фикснумом в качестве ключей

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

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

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

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

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

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

Ответы [ 2 ]

5 голосов
/ 30 марта 2011

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

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

2 голосов
/ 30 марта 2011

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

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

...