Ruby, как работает этот код? - PullRequest
1 голос
/ 05 марта 2012

Я новичок в Ruby и пытаюсь написать метод, который группирует массив слов в группы анаграмм.Вот код:

def combine_anagrams(words)
  dict = words.inject(Hash.new(0)) do |list,ws|
    key = sort_word(ws)
    if !list.has_key?(key)
      list[key] = []
    end
    list[key].push(ws)
    list             #What is this
  end
  return dict.values
end   

Мой вопрос - для чего утверждение list.Если я возьму его, список станет массивом вместо хеша.

Ответы [ 4 ]

1 голос
/ 05 марта 2012

inject работает следующим образом:

final = enumerable.inject(initial_value) do |current_value, iteration|
  # calculations, etc. here
  value # next iteration, current_value will be whatever the block returns
end

Итак, в вашем случае initial_value - это Hash.new(0), или пустой хэш с 0 в качестве значения по умолчанию для ключа, который нене существует вместо nil.Это передается в блок inject для первого элемента в enumerable.

Внутри блока ввода вы проверяете, существует ли уже key как ключ в хэше.Если это не так, установите его равным пустому массиву.В любом случае возьмите текущую итерацию words (ws) и поместите ее в массив.

Наконец, блок возвращает текущую версию list;он становится current_value (первый параметр в блоке inject) в следующий раз, когда цикл обрабатывает элемент из enumerable.

. В качестве более простого примера посмотрите этот пример:

numbers = [1, 2, 3, 4]
sum = inject(0) do |total, number| # first time, total will be 0
  total + number # set total next time to be whatever total is now plus the current number
end
1 голос
/ 05 марта 2012

Каждый метод / блок / и т.д. в Ruby что-то возвращает, и если только нет раннего оператора return, независимо от последнего оператора в методе / блоке / и т.д. есть то, что возвращается.

В вашем случае, если list будет последней строкой в ​​блоке, переданной в inject, гарантирует, что list будет возвращено блоком. Когда вы удаляете его, возвращается значение list[key].push(ws), что, очевидно, не то, что вы хотите.

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

На несвязанной ноте: ваш if !list.has_key?(key) может быть переписан unless list.has_key?(key).

0 голосов
/ 05 марта 2012

оператор «список» является возвращаемым значением всего блока.Строка: «list [key] = []» имеет возвращаемое значение «list», поэтому для установки возвращаемого значения условия if в «list» не требуется другая строка, кроме возвращаемого значения list [key].push (ws) - это список [ключ].мы хотим получить обновленное значение списка в конце, поэтому нам нужно каждый раз возвращать это значение из блока, чтобы дальнейшая обработка действовала для обновленного списка, а не для чего-то другого.

В качестве фонакаждая строка ruby ​​также имеет возвращаемое значение, поэтому, если это последняя строка блока или функции, она автоматически становится возвращаемым значением всего блока или функции соответственно.

Чтобы понять это далеепопробуйте такой код в irb:

a = [1,2,3,4,5]
b = a.inject(0) {|sum, val| puts sum; puts val; sum + val}

внутренний блок состоит из трех состояний;последний оператор возвращает значение sum + val в блок, который хранится в sum для использования в следующих итерациях.

Также попробуйте какой-нибудь код, подобный этому:

h = {:a => []}
b = h[:a].push 6

Посмотрите, что б оценивает;в вашем коде вам нужно, чтобы b был накопленным хешем, а не массив, который хранится в h [: a]

0 голосов
/ 05 марта 2012

Взгляните на http://ruby -doc.org / core-1.9.3 / Enumerable.html # method-i-inject

В методе inject, если вы передаете ему два аргумента (в вашем списке дел и в ws), первый - список - это так называемое значение аккумулятора. Значение, которое возвращается блоком ввода на каждом шаге итерации, присваивается переменной списка. Таким образом, строка с единственным словом «список», который вы прокомментировали как «#Что это», используется для присвоения значения списка в блоке переменной-аккумулятору «список».

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