Почему `Ha sh .new {| h, k | []} `вызывает` hash [char] << idx` для прекращения работы - PullRequest
0 голосов
/ 12 февраля 2020

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

def dupe_indices(arr)
  hash = Hash.new {|h,k| []}
  arr.each.with_index do |char,idx|
    hash[char] << idx
  end
  return hash
end

Странно то, что, несмотря на hash[char] инициализируется как пустой массив, hash[char] << idx не будет работать. Ха sh окажется пустым: {}.

Я могу решить эту проблему, либо инициализировав га sh, используя Hash.new {|h,k| h[k] = []}, либо изменив hash[char] << idx на hash[char] = hash[char].push[idx] для назначения.

Ответы [ 2 ]

2 голосов
/ 12 февраля 2020

Я могу решить проблему, инициализировав ha sh с помощью Hash.new {|h,k| h[k] = []} или [...]

Это действительно правильный способ использования варианта блока. Из документов на Hash.new:

"Блок обязан сохранить значение в га sh, если требуется."

Блок вызывается при доступе к пропущенным значениям через Hash#[]. Если вы не сохраните значение, га sh останется пустым. Поэтому в следующий раз, когда вы попытаетесь получить доступ к этому значению, оно все равно будет отсутствовать, и блок будет вызван снова:

hash = Hash.new { rand }

hash[:foo] #=> 0.9548960551853385
hash[:foo] #=> 0.7535154376706064
hash[:foo] #=> 0.007113200178872958
hash[:foo] #=> 0.07621008793193496

hash #=> {}

То же самое происходит с вашей попыткой Hash.new { [] } - вы получите fre * Массив 1030 * каждый раз, когда вы вызываете hash[char], потому что массив никогда не сохраняется в ha sh. Ваш код эквивалентен:

def dupe_indices(arr)
  hash = {}
  arr.each.with_index do |char, idx|
    [] << idx  # <- obviously doesn't do anything useful
  end
  return hash
end
0 голосов
/ 13 февраля 2020

Работает, когда hash[char] << idx заменяется на hash[char] <<= idx.

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