如何为数组中所有先前的值添加值

发布于 2024-09-01 10:45:19 字数 403 浏览 4 评论 0原文

假设我有以下数组:

my_array = [1, 5, 8, 11, -6]

我需要迭代该数组并将当前值之前的值添加在一起。举个例子可能会更容易理解。我需要返回一个看起来像这样的数组:

final_array = [1, 6, 14, 25, 19]

我尝试过这样做:

my_array.collect {|value| value + previous_values }

但显然这不起作用,因为我不知道如何获取数组中以前的值。

我是一个编程新手,所以这可能比我做的更容易。我很确定我需要使用收集或注入,但我似乎不知道如何做到这一点。

任何帮助将不胜感激。

Lets say I have the following array:

my_array = [1, 5, 8, 11, -6]

I need to iterate over this array and add the values prior to the current value together. An example will probably be easier to understand. I need to return an array that should look something like this:

final_array = [1, 6, 14, 25, 19]

I have tried doing something like this:

my_array.collect {|value| value + previous_values }

But obviously that doesn't work because I can't figure out how to get the previous values in the array.

I am a programming noob so this might be easier than I am making it. I am pretty sure I need to use either collect or inject, but I can't seem to figure out how to do this.

Any help would be appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

终弃我 2024-09-08 10:45:19

我的第一直觉是:“这显然是一次扫描(又名前缀求和),所以这应该很容易”:

[1, 5, 8, 11, -6].scan(:+)

显然,我最近读了太多的 Haskell 和 Scala,因为 没有 Ruby 中的 Enumerable#scan ...但是:

module Enumerable
  def scan(initial=first, &block)
    [initial].tap {|res| 
      reduce {|acc, el| 
        block.(acc, el).tap {|el|
          res << el
        }
      }
    }
  end
end

如果您希望 Enumerable#scan 表现得像 Enumerable#reduce,即采用可选的初始参数并一个可选符号,我们需要使用从 Rubinius 的 Enumerable#reduce 窃取的一些参数按摩代码来稍微增强我们的版本:

module Enumerable
  def scan(initial=nil, sym=nil, &block)
    args = if initial then [initial] else [] end
    unless block_given?
      args, sym, initial = [], initial, first unless sym
      block = ->(acc, el) { acc.send(sym, el) }
    end
    [initial || first].tap {|res| 
      reduce(*args) {|acc, el| 
        block.(acc, el).tap {|e|
          res << e
        }
      }
    }
  end
end

有了这个增强版本,上面的示例现在可以工作了:

p [1, 5, 8, 11, -6].scan(:+)
# => [1, 6, 14, 25, 19]

如果您再次遇到此类问题,在另一种语言中,请记住术语 scanprefix-sum,此类函数通常非常常见。我不太明白为什么 Ruby 还没有它们。

My very first instinct was: "That's obviously a scan (aka prefix-sum), so that should be easy":

[1, 5, 8, 11, -6].scan(:+)

Obviously, I've been reading way too much Haskell and Scala lately, because there is no Enumerable#scan in Ruby … yet:

module Enumerable
  def scan(initial=first, &block)
    [initial].tap {|res| 
      reduce {|acc, el| 
        block.(acc, el).tap {|el|
          res << el
        }
      }
    }
  end
end

If you want Enumerable#scan to behave like Enumerable#reduce, i.e. take an optional initial argument and an optional symbol, we need to enhance our version slightly with some argument massaging code stolen from Rubinius's Enumerable#reduce:

module Enumerable
  def scan(initial=nil, sym=nil, &block)
    args = if initial then [initial] else [] end
    unless block_given?
      args, sym, initial = [], initial, first unless sym
      block = ->(acc, el) { acc.send(sym, el) }
    end
    [initial || first].tap {|res| 
      reduce(*args) {|acc, el| 
        block.(acc, el).tap {|e|
          res << e
        }
      }
    }
  end
end

With this enhanced version, the example above now works:

p [1, 5, 8, 11, -6].scan(:+)
# => [1, 6, 14, 25, 19]

If you have this kind of problem again, in another language, remember the terms scan and prefix-sum, such functions are usually pretty common. I don't quite understand why Ruby doesn't have them already.

终陌 2024-09-08 10:45:19

您自己使用 collect 进行的尝试已经非常接近了;只要继续对之前的值进行求和就可以了。

my_array = [1, 5, 8, 11, -6]
previous_values = 0
my_array.collect { |value| previous_values += value }
# => [1, 6, 14, 25, 19]

Your own attempt at it with collect was already very close; just keep summing the previous values as you go.

my_array = [1, 5, 8, 11, -6]
previous_values = 0
my_array.collect { |value| previous_values += value }
# => [1, 6, 14, 25, 19]
伪心 2024-09-08 10:45:19
x = 0
[1, 5, 8, 11, -6].map {|a| x = x +a }
x = 0
[1, 5, 8, 11, -6].map {|a| x = x +a }
一杆小烟枪 2024-09-08 10:45:19

你可以使用这个:

my_array = [1, 5, 8, 11, -6]
final_array = []

my_array.inject(0) {|res, it| final_array << res + it; res + it}

You can use this:

my_array = [1, 5, 8, 11, -6]
final_array = []

my_array.inject(0) {|res, it| final_array << res + it; res + it}
聽兲甴掵 2024-09-08 10:45:19
my_array.each_index{|i| my_array[i] += my_array[i-1] if i>0 }

或者

my_array.inject([]){|memo, item| memo << item + memo.last.to_i }
my_array.each_index{|i| my_array[i] += my_array[i-1] if i>0 }

or

my_array.inject([]){|memo, item| memo << item + memo.last.to_i }
葬心 2024-09-08 10:45:19

我为此制作了一个预分配结果数组的 gem。即使对于具有大量元素的 Enumerables,操作也非常快。与使用 Enumerable#map 的解决方案不同,其语法与 Enumerable#reduce 的语法完全相同,并且可以选择在幕后使用 Enumerable#reduce,以防您使用猴子修补的 #reduce。该名称取自 Clojure 的同名函数。

https://rubygems.org/gems/reductions

安装:

$ gem install reductions

使用:

require 'reductions'

[1, 5, 8, 11, -6].reductions(:+)            #=> [1, 6, 14, 25, 19]
[1, 5, 8, 11, -6].reductions{|a| a + b}     #=> [1, 6, 14, 25, 19]

# With an inital value:
[1, 5, 8, 11, -6].reductions(1,:+)          #=> [1, 2, 7, 15, 26, 20]
[1, 5, 8, 11, -6].reductions(1){|a| a + b}  #=> [1, 2, 7, 15, 26, 20]

I made a gem for this that pre-allocates the result array. The operation is very fast, even for Enumerables with a large number of elements. Unlike solutions using Enumerable#map, the syntax is exactly like that of Enumerable#reduce, and can optionally use Enumerable#reduce under the hood in case you have monkey-patched #reduce. The name was taken from Clojure's function of the same name.

https://rubygems.org/gems/reductions

To install:

$ gem install reductions

To use:

require 'reductions'

[1, 5, 8, 11, -6].reductions(:+)            #=> [1, 6, 14, 25, 19]
[1, 5, 8, 11, -6].reductions{|a| a + b}     #=> [1, 6, 14, 25, 19]

# With an inital value:
[1, 5, 8, 11, -6].reductions(1,:+)          #=> [1, 2, 7, 15, 26, 20]
[1, 5, 8, 11, -6].reductions(1){|a| a + b}  #=> [1, 2, 7, 15, 26, 20]
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文