如何在Ruby中使用inject和next?

10
我正在编写以下代码:

我正在编写以下代码:

[1,2,3,4,5].inject([]) do |res, a|
  res << a*a and next if a == 2
  res << a
end

它会显示以下错误:

NoMethodError: undefined method `<<' for nil:NilClass

当使用next时,会将变量res置为nil,如何解决这个问题呢?

我尝试了各种方法,但无法让next与Ruby配合使用。我知道我提供的这个片段可以在没有next的情况下完成(a == 4 ? res << a*a : res << a),但在我的实际用例中,我有一些复杂的逻辑,不能这样简单地完成。

2个回答

14
替换

标签。

res << a*a and next if a == 2

使用

next res << a*a if a == 2

现在,它会工作。

例子:

#!/usr/bin/env ruby

ar = [1,2,3,4,5].inject([]) do |res, a|
  next res << a*a if a == 2
  res << a
end

p ar
# >> [1, 4, 3, 4, 5]

阅读 next 的文档

next 可以接受一个值,该值将成为当前块迭代的返回值....


4

哎呀,不要使用尾随条件语句来实现这个功能。相反,可以使用标准的 if/else 语句轻松完成:

[1,2,3,4,5].inject([]) do |res, a|
  if a == 2
    res << a*a
  else
    res << a
  end
end
# => [1, 4, 3, 4, 5]

任何时候你感觉自己已经陷入了代码的死胡同,不要试图寻找出路,相反,退后一步,看看你想要完成什么,是否有更加简单直接的方法。
我可能会再对代码进行一些调整以提高可读性。长期维护需要快速理解正在发生的事情,而混淆或不明显的代码可能会在以后造成问题。
[1,2,3,4,5].inject([]) do |res, a|
  if a == 2
    res << a*a
  else
    res << a
  end

  res # return it for clarity in what the block is returning
end
# => [1, 4, 3, 4, 5]

injecteach_with_object类似,只是依赖于累加器在块的结尾被返回,这就是为什么我会在块的末尾添加res以增加清晰度,由于if块的原因。转换到each_with_object可以消除对块返回值的依赖,使以下代码更加逻辑清晰:

[1,2,3,4,5].each_with_object([]) do |a, ary|
  if a == 2
    ary << a*a
  else
    ary << a
  end
end
# => [1, 4, 3, 4, 5]

当然,在那个时候,整个事情可以进一步简化,并且可以利用使用三元版本:

[1,2,3,4,5].each_with_object([]) do |a, ary|
  a2 = (a == 2) ? a * a : a
  ary << a2
end
# => [1, 4, 3, 4, 5]

以上两种写法哪个更容易阅读,有一定程度上取决于编写代码和维护代码的人。我倾向于非三元运算符版本,因为它更容易扩展和扩展,并且没有三元运算符?:链的干扰。
自从在评论中提出后,map减少了一些噪音,这也是我们应该转换数组的方式:
[1,2,3,4,5].map { |a|
  (a == 2) ? a * a : a
}

这个还没有经过测试,但看起来是正确的。

我非常同意。回答精彩。 - Patrice Gahide
@PatriceGahide 问题可能是,为什么我的“next”不起作用? :-) 不是如何更好地编写它。 - Arup Rakshit
1
我想表达的是要超越眼前问题,找到最清晰的解决方案。map确实是最好、最快的方法,但injecteach_with_object也可以使用。 - the Tin Man
当结果代码不是良好的编程实践时,直接回答问题就没有多大意义。使用 next 可能有效,但它是否是解决方案的适当编码方式呢?不是的。相反,我们应该指导和教育,让其他人学习并传授正确的技术。我们需要教别人如何钓鱼,而不是给他们鱼。 - the Tin Man
我知道三元/映射可以用于我所举的例子,但正如我已经说明的那样,在我的实际用例中,我有一些复杂的逻辑,不能简单地通过映射或三元版本完成。 - Saurabh
@ArupRakshit 当然,你的回答很好地解决了这个具体问题 ;) 至于其他方面,Tin Man已经回答了。再次,我同意他的观点,但我错过了saurabh说逻辑实际上比那更复杂的部分。我仍然怀疑实际代码可以以更可读的方式编写而不需要这种结构,但这个问题肯定会与http://codereview.stackexchange.com/重叠。 - Patrice Gahide

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接