2010-05-17 82 views
1

可以說我有以下數組:我如何增加價值,所有以前的值在陣列

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

我需要遍歷數組的值和電流值之前加在一起。一個例子可能會更容易理解。我需要返回一個數組,應該是這個樣子:

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

我試圖做這樣的事情:

my_array.collect {|value| value + previous_values } 

但顯然不行,因爲我無法弄清楚如何獲取數組中的前一個值。

我是一個編程noob,所以這可能比我更容易。我很確定我需要使用收集或注入,但我似乎無法弄清楚如何做到這一點。

任何幫助,將不勝感激。

+0

酷。感謝大家。我會給這些鏡頭。非常感謝。 – James 2010-05-17 08:46:56

回答

6

你在它自己的嘗試與collect已經非常接近;只要繼續總結以前的值。

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

注入不太可能工作,因爲memo.last最初將返回零。 – Anton 2010-05-17 08:26:23

+0

是的,你是對的。我認爲它會自動轉換爲int,但不是,所以顯式地添加了'to_i'。 – 2010-05-17 08:28:18

+0

似乎不必要地複雜,必須在這兩種解決方案中作出第一個元素的特例。 – Arkku 2010-05-17 08:53:05

3
x = 0 
[1, 5, 8, 11, -6].map {|a| x = x +a } 
1

您可以使用此:

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

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

我的第一個反應是:「這顯然是一個掃描(又名前綴總和),這樣應該很容易」:

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

很顯然,我已經讀了太多的哈斯克爾和最近的斯卡拉,因爲沒有Enumerable#scan在Ruby&hellip;又:

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] 

如果你有這樣的問題又來了,在另一種語言,還記得條款掃描前綴和,這樣的功能通常是很常見的。我不明白爲什麼Ruby沒有它們。

+0

我分享你的直覺....這是相當荒謬的,這從一開始就不是內建的...... – Jonah 2017-08-14 03:50:38

1

我爲此做了一個預分配結果數組的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]