Ruby注入以创建数组

时间:2016-03-01 17:43:13

标签: ruby-on-rails ruby

我有这段代码

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

第一个nb符合条件,res看起来像这个

["xxx1234"]

第二个nb删除/清除 res

的条件不匹配
nil

根据我的理解,第一个值应保留在数组中。

我也将它分配给一个变量,并希望它是一个单行。

3 个答案:

答案 0 :(得分: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。 e.g。

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

答案 1 :(得分:1)

如果您打开两个循环,但更清洁,仍然是单行:

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

答案 2 :(得分: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