我的第一個反應是:「這顯然是一個掃描(又名前綴總和),這樣應該很容易」:
[1, 5, 8, 11, -6].scan(:+)
很顯然,我已經讀了太多的哈斯克爾和最近的斯卡拉,因爲沒有Enumerable#scan
在Ruby…又:
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沒有它們。
酷。感謝大家。我會給這些鏡頭。非常感謝。 – James 2010-05-17 08:46:56