Подтвердить что ты не робот

Что такое Ruby-эквивалент Python defaultdict?

В Python я могу создать хэш, где каждый элемент имеет значение по умолчанию, когда оно сначала ссылается (также известно как "автовивитация" ). Вот пример:

from collections import defaultdict
d = defaultdict(int)
d["new_key"] += 1
print d

Печать dict указывает, что значение для "new_key" равно 1.

Какой эквивалент в Ruby? Этот код вызывает ошибку:

d = {}
d[:new_key] += 1
puts d

test.rb:3:in `<main>': undefined method `+' for nil:NilClass (NoMethodError)
4b9b3361

Ответ 1

Для этого вы можете использовать первый аргумент метода Hash.new:

d = Hash.new 0
d[:new_key] += 1
d[:new_key] #=> 1
d[:foo]     #=> 0

Будьте осторожны - вы можете случайно изменить значение по умолчанию:

h = Hash.new("Go Fish")
h[:unknown_key]         #=> "Go Fish"
h[:unknown_key].upcase! #=> "GO FISH"
h[:next_key]            #=> "GO FISH"

Как указано в его ответе "mu is too short", лучше использовать proc, например:

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

Ответ 2

Вы можете назначить значение по default= используя default=:

d.default = 0

Обратите внимание, что это на самом деле не будет автоматически авививизировать, но просто заставит d[:new_key] возвращать ноль без фактического добавления ключа :new_key. default= также может вызвать проблемы, если вы собираетесь изменить значение по умолчанию; это означает, что d.default = [ ] почти всегда является ошибкой, поскольку массив не будет скопирован при доступе по умолчанию.

Лучший выбор обычно default_proc=:

d.default_proc = proc { |h, k| h[k] = 0 }

Это позволяет вам иметь различные значения по умолчанию и позволяет добавлять новый ключ (или не в зависимости от того, как proc процесс).

Вы также можете установить их при создании хэша:

d = Hash.new(0)
d = Hash.new { |h, k| h[k] = 0 }

Ответ 3

Стандартный метод new для Hash принимает блок. Этот блок вызывается в случае попытки доступа к ключу в Хэше, который не существует. Блок передается сам Хэш и запрошенный ключ (два параметра) и должен возвращать значение, которое должно быть возвращено для запрошенного ключа.

Это может быть использовано для создания автогенерируемого хеша, среди прочего:

h = Hash.new{ |h,k| h[k] = 'default value'}