代码之家  ›  专栏  ›  技术社区  ›  Greg Charles

使用Ruby注入时无类

  •  7
  • Greg Charles  · 技术社区  · 15 年前

    我刚接触Ruby,我对Inject方法有一个奇怪的问题。

    当我这样做的时候:

    (1..10).inject(0) {|count,x| count + 1}
    

    如预期,结果是10。但当我这样做

    (1..10).inject(0) {|count,x| count + 1 if (x%2 == 0)}
    

    我得到了一个错误:

    NoMethodError: undefined method `+' for nil:NilClass
        from (irb):43
        from (irb):43:in `inject'
        from (irb):43:in `each'
        from (irb):43:in `inject'
        from (irb):43
    

    我真的不明白为什么第二个例子中的计数是零,而不是第一个。在任何情况下,我如何使用inject计算从1到10的偶数?

    2 回复  |  直到 15 年前
        1
  •  14
  •   Paige Ruten    15 年前

    表达式 count + 1 if (x%2 == 0) 收益率 nil 当条件不成立时, count 设置为,因为这是Inject方法的性质。

    你可以回去修理它 count + 1 当它是一个偶数 计数 当它不是:

    (1..10).inject(0) { |count,x| x % 2 == 0 ? count + 1 : count }
    

    完全不同的解决方案是使用 select 选择偶数并使用 Array#length 计算它们的方法。

    (1..10).select { |x| x % 2 == 0 }.length
    
        2
  •  3
  •   pierrotlefou    15 年前

    AS yjerem 已经指出, count + 1 if (x%2 == 0) 将被评估为 nil 当x为奇数时。问题是: 值将分配给 count ,所以下一个迭代将是 nil + 1 ,导致报告错误。

    了解Inject的工作原理是很重要的(从 ruby-doc )

    Enum.Inject(初始)备忘录,obj块=>obj

    enum.inject备忘录,obj block=gt;obj

    通过将块依次应用于累加器值(memo)和每个元素来组合枚举元素。在每个步骤中,memo都被设置为块返回的值。第一个表单允许您为备忘录提供初始值。第二个表单使用集合的第一个元素作为初始值(并在迭代时跳过该元素)。

    规则将使您远离此类错误:块始终返回与累加器相同类型的值。如果您的示例,该块将返回 什么时候 x%2==0 如果 false .

    (1..10).inject(0) {|count,x| count + 1 if (x%2 == 0)}

    推荐文章