में संचयी सरणी राशि एक सरणी के संचयी योग की गणना करने का सबसे धीमा, सबसे रूबी-जैसा तरीका क्या है?रूबी
उदाहरण:
[1,2,3,4].cumulative_sum
[1,3,6,10]
में संचयी सरणी राशि एक सरणी के संचयी योग की गणना करने का सबसे धीमा, सबसे रूबी-जैसा तरीका क्या है?रूबी
उदाहरण:
[1,2,3,4].cumulative_sum
[1,3,6,10]
यहाँ वापस आना होगा एक ही रास्ता
a = [1, 2, 3, 4]
a.inject([]) { |x, y| x + [(x.last || 0) + y] }
अगर यह ठीक है कि इस सवाल का जवाब एक से अधिक बयान है, तो यह हो सकता है क्लीनर:
outp = a.inject([0]) { |x, y| x + [x.last + y] }
outp.shift # To remove the first 0
irb> a = (1..10).to_a
#=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
irb> a.inject([0]) { |(p,*ps),v| [v+p,p,*ps] }.reverse[1..-1]
#=> [1, 3, 6, 10, 15, 21, 28, 36, 45, 55]
हम भी हास्केल से लिख लेना चाहिए और scanr के एक गहरे लाल रंग का संस्करण बना सकते हैं।
irb> class Array
> def scanr(init)
> self.inject([init]) { |ps,v| ps.unshift(yield(ps.first,v)) }.reverse
> end
> end
#=> nil
irb> a.scanr(0) { |p,v| p + v }
=> [0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55]
irb> a.scanr(0) { |p,v| p + v }[1..-1]
=> [1, 3, 6, 10, 15, 21, 28, 36, 45, 55]
irb> a.scanr(1) { |p,v| p * v }
=> [1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800]
+1, यह एक संचित इंजेक्शन है। ध्यान दें कि आप केवल वर्ग ऐरे के बजाय मॉड्यूल के लिए स्कैनर जोड़ सकते हैं। – tokland
एक और दृष्टिकोण (हालांकि मैं khell के पसंद करते हैं)
(1..10).inject([]) { |cs, i| cs << i + (cs.last || 0) }
मैं अपने जवाब पोस्ट करने के बाद जवाब hrnt द्वारा पोस्ट की गई देखा। हालांकि दो दृष्टिकोण समान दिखते हैं, ऊपर समाधान अधिक कुशल है क्योंकि प्रत्येक इंजेक्शन चक्र में एक ही सरणी का उपयोग किया जाता है।
a,r = [1, 2, 3, 4],[]
k = a.inject(r) { |x, y| x + [(x.last || 0) + y] }
p r.object_id
# 35742260
p k.object_id
# 35730450
आप r और कश्मीर अलग हैं देखेंगे। यदि आप ऊपर दिए गए समाधान के लिए एक ही परीक्षण करते हैं:
a,r = [1, 2, 3, 4],[]
k = a.inject(r) { |cs, i| cs << i + (cs.last || 0) }
p r.object_id
# 35717730
p k.object_id
# 35717730
आर और के लिए ऑब्जेक्ट आईडी समान हैं।
cs.last.to_i में भी संशोधित किया जा सकता है - कम नहीं, लेकिन शायद अधिक पठनीय? – TCSGrad
इसके अलावा आप scanl
- सुविधा की आवश्यकता के बारे में पढ़ सकते हैं, लेकिन यह अभी तक रूबी में लागू नहीं है, जहां तक मुझे पता है। यहाँ उदाहरण और नमूना स्रोत यह कोड हैं: http://billsix.blogspot.com/2008/11/functional-collection-patterns-in-ruby.html
युपीडी: ऊपर के लिंक मर चुका है, इसलिए बजाय मैं कहूँगा कि Wolfram मेथेमेटिका के FoldList[] मणि के एक भाग के रूप में "MLL" here कर सकते हैं की मेरी रूबी कार्यान्वयन जबकि Enumerable जा रहा ओपी के प्रयोजन के लिए सरल किया जा:
def fold_list array
start = 0
Enumerator.new do |e|
array.each do |i|
e << start += i
end
end
end
irb> fold_list([1,2,3]).to_a
=> [1, 3, 6]
एक और दृष्टिकोण के लिए यह उजागर, कि सरणी को संशोधित करता है यथा-स्थान
class Array
def cumulative_sum!
(1..size-1).each {|i| self[i] += self[i-1] }
self
end
end
भी सामान्यीकृत किया जा सकता:
def cumulate!(&block)
(1..size-1).each {|i| self[i] = yield self[i-1], self[i] }
self
end
>> (1..10).to_a.cumulate! {|previous, next| previous * next }
=> [1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800]
इस कोड
[1,2,3,4].inject([]){ |acc, value| acc << acc.last.to_i + value.to_i }
=> [1, 3, 6, 10]
प्रयास करें हास्केल समारोह हम चाहते हैं scanl
, नहीं scanr
है।
class Array
def scanl(init)
self.reduce([init]) { |a, e| a.push(yield(a.last, e)) }
end
end
[1,2,3,4].scanl(0) { |a, b| a + b }[1..-1]
=> [1, 3, 6, 10]
केवल 5.5 साल बाद इस प्रश्न पर वापस आ रहा है! – Peter