2016-03-01 3 views
0

У меня есть этот кодРубин впрыснуть создать массив

notebooks.inject([]) do |res, nb| 
    res << nb.guid if Recipe::NOTEBOOKS.include?(nb.name) 
end 

Первый nb имеет соответствует условию и res выглядит следующим образом

["xxx1234"] 

Второго nb не соответствует условию, которое затем удалить/очищаетres

nil 

По моему мнению, первое значение должно оставаться в массиве.

Я также назначаю это переменной и хочу, чтобы она была одним лайнером.

ответ

4

inject работает немного по-другому от того, как вы себе. Он просто возвращает последнее возвращаемое значение цикла, когда оно проходит через каждый элемент. Самый простой способ исправить это:

notebooks.inject([]) do |res, nb| 
    res << nb.guid if Recipe::NOTEBOOKS.include?(nb.name) 
    res # Returns the res array 
end 

Тем не менее, вы, вероятно, следует использовать select для случая использования, как вы, кажется, просто фильтрация, по которой множество ноутбуков вы хотите .. То есть:

notebooks.select{|nb| Recipe::NOTEBOOKS.include?(nb.name)}.map(&:guid) 

Как правило, я использовал inject, когда мне нужно запустить математику по группе элементов. например

[1,2,3,4].inject(0) {|res, x| x * 2 + res} 
0

Аккумулятор должен быть возвращен на каждой итерации цикла:

notebooks.inject([]) do |res, nb| 
    Recipe::NOTEBOOKS.include?(nb.name) ? res << nb.guid : res 
end 

На самом деле, на каждой последующей итерации цикла, аккумулятор передается res параметра блока является именно то, что был возвращен из предыдущей итерации.

В вашем примере, на второй итерации if возвращает false и

res << nb.guid if Recipe::NOTEBOOKS.include?(nb.name) 

линия не выполняется вообще. Тем не менее, после второй итерации аккумулятор приобретает совершенно новое значение, то есть, видимо, nil.

1

Если вы открыты для двух петель, но чище и еще один лайнер:

notebooks.select { |nb| Recipe::NOTEBOOKS.include?(nb.name) }.map(&:guid) 
+1

+1 Именно то, о чем я думал. Это также помогает читабельности, потому что вы разделяете проблему на два разных шага. Я сломал бы его как минимум на 2 линии. – Kelvin

Смежные вопросы