Создание нового хэша с ключами по умолчанию - PullRequest
9 голосов
/ 06 мая 2011

Я хочу создать хеш с индексом из массива.

ary = ["a", "b", "c"]
h = Hash.new(ary.each{|a| h[a] = 0})

Моя цель - начать с хеша, подобного этому:

h = {"a"=>0, "b"=>0, "c"=>0}

, чтобы позжекогда хэш изменился, я могу сбросить его с помощью h.default

К сожалению, способ, которым я настраиваю хэш, не работает ... какие-либо идеи?

Ответы [ 6 ]

9 голосов
/ 06 мая 2011

Сначала вы должны создать свой хеш h, а затем заполнить его содержимым массива:

h = {}    
ary = ["a", "b", "c"]
ary.each{|a| h[a] = 0}
5 голосов
/ 07 мая 2011

Использовать функцию значения по умолчанию для хеша

h = Hash.new(0)

h["a"]      # => 0

В этом подходе ключ не установлен.

h.key?("a") # => false

Другой подход - установить отсутствующий ключ при доступе.

h = Hash.new {|h, k| h[k] = 0}
h["a"]      # => 0
h.key?("a") # => true

Даже при таком подходе такие операции, как key?, не будут выполнены, если вы ранее не обращались к клавише.

h.key?("b") # => false
h["b"]      # => 0
h.key?("b") # => true

Вы всегда можете прибегнуть к грубой силе с наименьшими граничными условиями.

h = Hash.new.tap {|h| ["a", "b", "c"].each{|k| h[k] = 0}}
h.key?("b") # => true
h["b"]      # => 0
3 голосов
/ 06 мая 2011

Вы можете сделать это следующим образом, расширив список до инициализированных нулями значений:

list = %w[ a b c ]

hash = Hash[list.collect { |i| [ i, 0 ] }]

Вы также можете создать хэш, который просто имеет значение по умолчанию 0 для любого заданного ключа:

hash = Hash.new { |h, k| h[k] = 0 }

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

2 голосов
/ 06 мая 2011

Возможно, это не самый эффективный способ, но я всегда ценю однострочники, которые раскрывают немного больше об универсальности Ruby:

h =  Hash[['a', 'b', 'c'].collect { |v|  [v, 0] }]

Или другой однострочник, который делает то же самое:

h = ['a', 'b', 'c'].inject({}) {|h, v| h[v] = 0; h }

Кстати, с точки зрения производительности, однострочники работают примерно на 80% скорости:

h = {}
ary = ['a','b','c']
ary.each { |a| h[a]=0 }
0 голосов
/ 08 июня 2017

Альтернативный способ иметь хеш с фактически добавленными ключами

Hash[[:a, :b, :c].zip([])] # => {:a=>nil, :b=>nil, :c=>nil}

Hash[[:a, :b, :c].zip(Array.new(3, 0))] # => {:a=>0, :b=>0, :c=>0}
0 голосов
/ 06 мая 2011

Другой вариант - использовать метод Enum#inject, поклонником которого я являюсь за его чистоту. Хотя я не сравнивал его с другими вариантами.

h = ary.inject({}) {|hash, key| hash[key] = 0; hash}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...