我正在计算从每个索引到数组末尾的数组值之和。像这样:
array = [50, 40, 30,20]
array.map.with_index{|x,i| x = array[i..array.length].reduce(:+) }
=> [140, 90, 50, 20]
有没有更清洁,像红宝石般的更有效的方法呢?已经讨论了累积数组和here。
答案 0 :(得分:7)
我定义了一个scanl
帮助器来收集reduce
的结果:
module Enumerable
def scanl(initial, sym)
self.reduce([initial]) { |m, n| m << m[-1].send(sym, n) }[1..-1]
end
end
scanr
向后执行此操作:
def scanr(initial, sym)
self.reverse_each.scanl(initial, sym).reverse
end
就是这样:
array.scanr(0, :+)
答案 1 :(得分:3)
正如您提到的那样有效,我没有按照 Best case Avg case Worst case
LS 1 comparison n/2 comp. n comp
BS 1 comparison O(log_n) O(log_n)
方式执行您的代码:它的时间复杂度为map.with_index
反向cumulative_sum可以使用cumulative_sum和2 O(n^2)
:
reverse
答案 2 :(得分:2)
这是一个棘手的方法:
sum = array.inject(a[-1], &:+)
array.map.with_index { |x, i| sum -= a[i-1] }
=> [140, 90, 50, 20]
答案 3 :(得分:1)
array.each_with_object([array.inject(:+)]){|e, a| a << a.last - e}[0...-1]
# => [140, 90, 50, 20]
答案 4 :(得分:1)
array.reverse_each.with_object([]) { |n,a| a.unshift(n + a.first.to_i) }
#=> [140, 90, 50, 20]
从数组的最后一个元素开始并向前工作,每个元素和a
的第一个元素(要构建的数组,要返回)的总和被推到{{1}的前面}。当a
为空时,
a
或者,可以写
a.first.to_i
#=> [].first.to_i => nil.to_i => 0
使用Array#reverse_each只需要一次通过(a.first || 0)
。