我想在数组中添加数字并忽略nil元素。我的解决方案显然不起作用。
array = [3,4,5,6,nil,9,nil,9,3]
def add(array)
array.inject(0){|memo,s|s.is_a?Integer ? memo+=s : next}
end
答案 0 :(得分:7)
您的版本无法正常工作的原因很简单:块的返回值将成为下一次迭代的memo
值。在s
不是Integer
的情况下,您只需返回任何内容,即nil
,因此在下一次迭代中,memo
为nil
。
您可以通过简单地返回备忘录来修复它:
def add(array)
array.inject(0) { |memo, s| s.is_a? Integer ? memo += s : next memo }
# ↑↑↑↑
end
这是解决问题的最小可能变化。
块通常返回块内部计算的最后一个表达式的值,因此实际上不需要next
:
def add(array)
array.inject(0) { |memo, s| s.is_a? Integer ? memo += s : memo }
end
分配给memo
没有任何意义,无论如何它都会超出范围的最后范围,你再也不会使用它了:
def add(array)
array.inject(0) { |memo, s| s.is_a? Integer ? memo + s : memo }
end
根据标准的社区风格指南,消息发送的参数列表应该括在括号中,除非它是一个"类似程序的"邮件发送(例如puts
,require
)或"类似关键字"一个(例如attr_accessor
):
def add(array)
array.inject(0) { |memo, s| s.is_a?(Integer) ? memo + s : memo }
end
就个人而言,我不喜欢条件运算符。这是一个风格问题,但我更喜欢这个:
def add(array)
array.inject(0) { |memo, s| if s.is_a?(Integer) then memo + s else memo end }
end
但是,更简单的解决方案是在迭代之前删除nil
元素:
def add(array)
array.reject {|s| s.nil? }.inject(0) { |memo, s| memo + s }
end
可以更优雅地编写
def add(array)
array.reject(&:nil?).inject(0) { |memo, s| memo + s }
end
但实际上只相当于更具可读性:
def add(array)
array.compact.inject(0) { |memo, s| memo + s }
end
def add(array)
array.compact.inject(0, :+)
end
这与sum
:
def add(array)
array.compact.sum
end
答案 1 :(得分:3)
使用compact
array.compact.reduce(0,:+)
答案 2 :(得分:1)
你可以采取多种方式:
array = [3,4,5,6,nil,9,nil,9,3]
array.sum(&:to_i) # => 39
array.reject(&:nil?).sum # => 39
您可以使用compact
代替reject(&:nil?)
:
array.compact.sum # => 39
如果您没有sum
可用,如果您使用的是合理的Ruby,则可以使用inject(:+)
:
array.compact.inject(:+) # => 39
require 'fruity'
compare do
sum_to_i { array.sum(&:to_i) }
reject_nil { array.reject(&:nil?).sum }
compact_reduce { array.compact.reduce(0,:+) }
compact_sum { array.compact.sum }
compact_inject { array.compact.inject(:+) }
do_not_do_this { array.reject{|a| a.nil?}.inject(0){|memo,a| memo+=a} }
end
# >> Running each test 8192 times. Test will take about 1 second.
# >> compact_sum is faster than compact_inject by 10.000000000000009% ± 10.0%
# >> compact_inject is similar to compact_reduce
# >> compact_reduce is faster than sum_to_i by 19.999999999999996% ± 10.0%
# >> sum_to_i is faster than reject_nil by 1.9x ± 0.1
# >> reject_nil is faster than do_not_do_this by 2.0x ± 0.1
Jörg's solution显然是最快的。
答案 3 :(得分:0)
我明白了:
array.reject{|a| a.nil?}.inject(0){|memo,a| memo+=a}