Конвертировать массив в хеш индекса в Ruby - PullRequest
42 голосов
/ 04 января 2009

У меня есть массив, и я хочу создать хеш, чтобы я мог быстро спросить «есть ли X в массиве?».

В Perl есть простой (и быстрый) способ сделать это:

my @array = qw( 1 2 3 );
my %hash;
@hash{@array} = undef;

Это генерирует хэш, который выглядит следующим образом:

{
    1 => undef,
    2 => undef,
    3 => undef,
}

Лучшее, что я придумал в Ruby:

array = [1, 2, 3]
hash = Hash[array.map {|x| [x, nil]}]

, что дает:

{1=>nil, 2=>nil, 3=>nil}

Есть ли лучший способ Ruby?

РЕДАКТИРОВАТЬ 1

Нет, Array.include? не очень хорошая идея Его медленно . Это делает запрос в O (n) вместо O (1). В моем примере для краткости было три элемента; Предположим, что фактический имеет миллион элементов. Давайте сделаем небольшой бенчмаркинг:

#!/usr/bin/ruby -w
require 'benchmark'

array = (1..1_000_000).to_a
hash = Hash[array.map {|x| [x, nil]}]

Benchmark.bm(15) do |x|
    x.report("Array.include?") { 1000.times { array.include?(500_000) } }
    x.report("Hash.include?") { 1000.times { hash.include?(500_000) } }
end

Производит:

                     user     system      total        real
Array.include?  46.190000   0.160000  46.350000 ( 46.593477)
Hash.include?    0.000000   0.000000   0.000000 (  0.000523)

Ответы [ 14 ]

1 голос
/ 04 января 2009

Может быть, я неправильно понимаю цель здесь; Если вы хотите узнать, есть ли X в массиве, почему бы не сделать array.include? ("X")?

0 голосов
/ 21 апреля 2014

Это сохраняет 0, если ваш хэш был [0,0,0,1,0]

  hash = {}
  arr.each_with_index{|el, idx| hash.merge!({(idx + 1 )=> el }) }

Возвращает:

  # {1=>0, 2=>0, 3=>0, 4=>1, 5=>0}
0 голосов
/ 04 января 2009

Вот изящный способ кэширования поиска с помощью хэша:

a = (1..1000000).to_a
h = Hash.new{|hash,key| hash[key] = true if a.include? key}

Практически все, что он делает, это создает конструктор по умолчанию для новых значений хеша, а затем сохраняет «true» в кеше, если он находится в массиве (в противном случае - ноль). Это позволяет выполнять отложенную загрузку в кэш, на случай, если вы не используете каждый элемент.

0 голосов
/ 04 января 2009

Если вы ищете эквивалент этого Perl-кода:

grep {$_ eq $element} @array

Вы можете просто использовать простой код Ruby:

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