【问题标题】:Yielding a modified Ruby array to a block将修改后的 Ruby 数组生成为块
【发布时间】:2017-06-08 09:11:45
【问题描述】:

我正在尝试将 2 行 ruby​​ 代码变成 1 行。例如:

def average(numbers)
  result = numbers.compact
  numbers.reduce(+) / numbers.length
end

我一直在查看数组方法,但找不到合适的方法来将此函数变成单行。我曾希望这样的事情会奏效:

def average(numbers)
  numbers.compact.<tap or another method> { |arr| arr.reduce(+) / arr.length }
end

基本上,我正在修改数组(在示例中,我必须调用 compact 来删除 nil 值),因此我无法访问数组变量,并且我不想要迭代器,因为我不想在数组的单个元素上调用 reduce(+)length

有人知道我可以研究的方法吗?

【问题讨论】:

    标签: arrays ruby methods


    【解决方案1】:

    你可以改变你打电话给average的方式

    def average(numbers)
      numbers.reduce(:+) / numbers.length
    end
    
    average(num_array.compact)
    

    【讨论】:

    • 谢谢。无论如何,我认为我对“我无权访问数组变量”部分感到困惑。
    【解决方案2】:

    我相信你的意思是你的方法如下(reduce(:+),而不是reduce(+),并在第二行使用result而不是numbers)。

    def average(numbers)
      result = numbers.compact
      result.reduce(:+) / result.length
    end
    
    average [1,2,3]
      #=> 2
    

    如果您希望平均值为浮点数,请将第二行更改为

    result.reduce(0.0, :+) / result.length
    

    有多种方法可以组合方法的两行,但我不喜欢上面的任何一种。这里有几个。 (我不明白Object#tap 可以在这里使用。)

    numbers.compact.reduce(:+) / numbers.compact.length
    
    (result = numbers.compact).reduce(:+) / result.compact.length
    
    numbers.map(&:to_i).reduce(:+) / numbers.compact.length
    

    请注意,即使numbers 可以变异,也不能写入

    numbers.compact!.reduce(:+) / numbers.length
    

    因为如果numbers 不包含nil 元素,numbers.compact! 将返回nil

    在 Ruby v2.4+ 中,您可以使用 Array#sum:

    result.sum / result.length
    

    【讨论】:

    • 酷,我刚刚和我的一位队友谈过,我们一致认为我所拥有的(加上你的更正)最适合可读性。
    • 虽然我确实在这里学到了一些东西:(result = numbers.compact).reduce(:+) / result.compact.length 谢谢!
    • 感谢@Stefan 的更正。我的意思是将平均值的计算写为 result.reduce(:+).to_f / result.length 的浮点数,但我更喜欢你这样做的方式。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-10-02
    • 2014-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-04
    • 2014-05-22
    相关资源
    最近更新 更多