रूबी में संख्याओं का योग कैसे करें?


563

मेरे पास एक पूर्णांक है।

उदाहरण के लिए:

array = [123,321,12389]

क्या उनके योग का कोई अच्छा तरीका है?

मुझे पता है

sum = 0
array.each { |a| sum+=a }

काम करेगा।


19
कृपया ध्यान दें कि रूबी 2.4+ के पासarray.sum
dawg

रूबी 2.6 में यह नहीं है। रूबी पार्थ, रूबी दूर, ऐसा लगता है।
लोरी

1
@ लोरी हम्म? लिंक
स्टीवेंसल

माफ़ करना। उस समय मैंने गलती से माना था कि मैं अपने हिस्से पर रेंबव स्लिप-अप के कारण 2.6 का उपयोग कर रहा था।
लोरी

जवाबों:


612

इसे इस्तेमाल करे:

array.inject(0){|sum,x| sum + x }

देखिए रूबी का दमदार डॉक्यूमेंटेशन

(ध्यान दें: 0आधार मामले की आवश्यकता है ताकि 0एक खाली सरणी पर लौटा दिया जाए nil)


317
ज्यूरिस array.inject(:+)अधिक कुशल है।
पीटर

3
array.inject(:+)रूबी में परेशानी का कारण लगता है 1.8.6 अपवाद "LocalJumpError: कोई ब्लॉक नहीं दिया गया" पॉप अप हो सकता है।
कामिल स्ज़ोट

34
रेल में array.sumआप सरणी मूल्यों का योग दे सकते हैं।
कामिल एसज़ोट

32
ज्यादातर मामलों में, मैं उपयोग करना पसंद करता हूं reduce, जो inject(जैसा कि array.reduce( :+ )) का एक उपनाम है ।
बोरिस स्टिटनिक

3
@ बोरिस भी, रूबिकॉप आपको इसके injectबजाय उपयोग करने के लिए चेतावनी देगा reduce
दरोगाओं का

810

या रूबी 1.9 तरीका आज़माएँ:

array.inject(0, :+)

नोट: 0आधार मामले की जरूरत है अन्यथा nilखाली सरणियों पर लौटा दिया जाएगा:

> [].inject(:+)
nil
> [].inject(0, :+)
0

6
मैं ऑब्जेक्ट से किसी विशेषता को योग करने के लिए इस तरह से कैसे उपयोग कर सकता हूं। मेरी सरणी [product1, product2] मैं product1.price + product2.price योग करना चाहता हूं। क्या array.inject (: +) का उपयोग करना संभव है?
पाब्लो कैंटरो

7
आप मैप विधि के साथ एक समान ट्रिक का उपयोग कर सकते हैं: array.map (&: price) .inject (: +)
markquezada

100
array.map(&:price).inject(0, :+)थोड़ा सुरक्षित है। यह सुनिश्चित करता है कि यदि आपके पास खाली सूची है तो आपको शून्य के बजाय 0 मिलता है ।
जोंफ

11
array.map (...) इंजेक्षन (...) का उपयोग करना अक्षम है, आप दो बार सभी डेटा के माध्यम से पुनरावृति करेंगे। कोशिश करें array.inject(0) { |sum, product| sum += product.price }
everett1992

4
@ everett1992 और जैसा कि यह पता चला है, बिल्कुल भी अनुकूलन नहीं है। इसे दो चरणों में करना मेरे लिए लगातार तेज है। gist.github.com/cameron-martin/b907ec43a9d8b9303bdc
कैमरून मार्टिन

290
array.reduce(0, :+)

जबकि समतुल्य array.inject(0, :+), टर्म कम करना MapReduce प्रोग्रामिंग मॉडल के उदय के साथ एक अधिक सामान्य वर्नाक्यूलर में प्रवेश कर रहा है ।

सुई , को कम करने , गुना , संचित , और संपीड़ित सभी के एक वर्ग के रूप में पर्याय बन गया है कार्यों तह । मुझे आपके कोड आधार में निरंतरता सबसे महत्वपूर्ण लगती है, लेकिन चूंकि विभिन्न समुदाय एक शब्द को दूसरे पर पसंद करते हैं, इसलिए विकल्प जानना गैर-उपयोगी है।

मानचित्र-कम करने की क्रिया पर जोर देने के लिए, यहां एक संस्करण है जो उस सरणी में समाप्त होने पर थोड़ा अधिक क्षमा करने योग्य है।

array.map(&:to_i).reduce(0, :+)

कुछ अतिरिक्त प्रासंगिक पढ़ने:


11
मैं सहमत हूं, reduceमुझे बताता है कि फ़ंक्शन क्या करता है, लेकिन injectबहुत कूलर ध्वनि करता है।
everett1992

1
अंतिम टिप्पणी से सहमत हूं, आपने मुझे सबसे अच्छा जवाब दिया।
जर्सका

1
एक टिप्पणी जो मैं करूंगा वह है reduceऔर mapउच्च-क्रम के कार्यों के रूप में MapReduce की भविष्यवाणी। प्रेरणा दूसरे तरीके से चलती है। और MapReduce के अर्थ में, यह एक साधारण कार्यात्मक कमी की तुलना में कुछ अलग ऑपरेशन है, विभिन्न मशीनों के संचार के लिए निहितार्थ हैं।
अचज

केन इवरसन ने प्रोग्रामिंग भाषा एपीएल में ऑपरेटर / "कमी ऑपरेटर" कहा। स्रोत: इवरसन, केनेथ 1962. एक प्रोग्रामिंग भाषा। विले। एक अन्य स्रोत: "थॉट्स अ टूल के रूप में सूचना", 1979 ACM ट्यूरिंग अवार्ड लेक्चर, केनेथ ई। इवरसन, dl.acm.org/ft_gateway.cfm?id=1283935&type=pdf
फर्नांडो

112

वैकल्पिक रूप से (केवल तुलना के लिए), यदि आपके पास रेल स्थापित है (वास्तव में सिर्फ ActiveSupport):

require 'activesupport'
array.sum

12
Activesupport के नए संस्करण वास्तव में डिफ़ॉल्ट रूप से सभी एक्सटेंशन लोड नहीं करते हैं। आप या तो केवल योग मॉड्यूल की आवश्यकता चाहते हैं: require 'active_support/core_ext/enumerable.rb'या सभी सक्रिय समर्थन की आवश्यकता है require 'active_support/all':। इसके बारे में यहाँ और अधिक: एपीआई डॉक्स
डीसीएचमैन

2
कोई बात नहीं है कि से जाने के लिए एक परियोजना में खींचने के लिए activesupportएक बड़े पैमाने पर निर्भरता array.inject(:+)है array.sum
meagar

1
अन्यथा अच्छी टिप्पणी के लिए निपिक: यह प्रत्यय के require 'active_support/core_ext/enumerable'बिना होना चाहिए .rb, क्योंकि इसमें निहित है।
लुंडबर्ग

72

रूबी> = 2.4.0 के लिए आप sumEnumerables से उपयोग कर सकते हैं ।

[1, 2, 3, 4].sum

आधार क्लासेस को रोकना खतरनाक है। आप खतरे और रूबी के एक पुराने संस्करण का उपयोग कर चाहें, तो आप जोड़ सकते हैं #sumकरने के लिए Arrayवर्ग:

class Array
  def sum
    inject(0) { |sum, x| sum + x }
  end
end

1
कृपया ऐसा न करें
user3467349

@ user3467349 क्यों?
YoTengoUnLCD

15
मंकीपैकिंग बेस क्लास अच्छी नहीं है।
user3467349

1
वह जो बिंदु बना रहा है वह यह है कि आपको रूबी> = 2.4 के लिए मंकी पैच करने की आवश्यकता नहीं है, और यह कि बंदर पैचिंग खतरनाक है, और अब आप मूल रूप से गणना कर सकते हैं, लेकिन कार्यक्षमता को वापस लाने का एक तरीका भी है।
पीटर एच। बोलिंग

डाउनवोट किया गया क्योंकि आपका कार्यान्वयन रिक्त सरणियों पर शून्य देता है।
एल्ड्रिच कोन्ड्रम

45

रूबी 2.4.0 के लिए नया

आप उपयुक्त नाम पद्धति का उपयोग कर सकते हैं Enumerable#sum। इसके बहुत सारे फायदे हैं inject(:+)लेकिन अंत में भी पढ़ने के लिए कुछ महत्वपूर्ण नोट्स हैं।

उदाहरण

सीमाओं

(1..100).sum
#=> 5050

Arrays

[1, 2, 4, 9, 2, 3].sum
#=> 21

[1.9, 6.3, 20.3, 49.2].sum
#=> 77.7

महत्वपूर्ण लेख

यह विधि नहीं के बराबर है #inject(:+)। उदाहरण के लिए

%w(a b c).inject(:+)
#=> "abc"
%w(a b c).sum
#=> TypeError: String can't be coerced into Integer

इसके अलावा,

(1..1000000000).sum
#=> 500000000500000000 (execution time: less than 1s)
(1..1000000000).inject(:+)
#=> 500000000500000000 (execution time: upwards of a minute)

ऐसा क्यों sumहै के बारे में अधिक जानकारी के लिए यह उत्तर देखें ।


19

विविधता के लिए, आप यह भी कर सकते हैं यदि आपकी सरणी संख्याओं की एक सरणी नहीं है, बल्कि उन वस्तुओं की एक सरणी है जिनमें गुण हैं जो संख्याएँ हैं (जैसे राशि):

array.inject(0){|sum,x| sum + x.amount}

3
यह करने के बराबर है array.map(&:amount).inject(0, :+):। अन्य उत्तर देखें।
रिचर्ड जोन्स

4
एक तरह से, हाँ। हालाँकि, mapतब injectआपको दो बार सरणी के माध्यम से लूप की आवश्यकता होती है: एक बार एक नया सरणी बनाने के लिए, दूसरा सदस्यों को योग करने के लिए। यह विधि थोड़ी अधिक क्रियात्मक है, लेकिन अधिक कुशल भी है।
हैशफेल

जाहिरा तौर पर यह अधिक कुशल नहीं है, देखें gist.github.com/cameron-martin/b907ec43a9d8b9303bdc - इस उत्तर में टिप्पणियों का श्रेय: stackoverflow.com/a/1538.149/1028679
rmcsharry

19

रूबी 2.4+ / रेल्स - array.sumअर्थात[1, 2, 3].sum # => 6

रूबी पूर्व 2.4 - array.inject(:+)याarray.reduce(:+)

* नोट: #sumविधि 2.4 के लिए एक नया अतिरिक्त है, enumerableइसलिए अब आप array.sumकेवल रेल में नहीं बल्कि शुद्ध रूबी में उपयोग कर पाएंगे ।


2
रूबी 2.4.0 आज इस सुविधा के साथ जारी किया गया था! 🎉
amoebe

@amoebe तुम सही हो! इस उपयोगी सुविधा को देखकर खुशी हुई।
इकट्ठा करें

18

रूबी 1.8.7 तरीका निम्नलिखित है:

array.inject(0, &:+) 

यदि आप मेरी 2011 की टिप्पणी पढ़ते हैं, और यह अभी भी प्रासंगिक है जैसा कि आप 1.8.6 का उपयोग कर रहे हैं, तो कृपया अपग्रेड करें!
एंड्रयू ग्रिम

16

आप बस का उपयोग कर सकते हैं:

    example = [1,2,3]
    example.inject(:+)

यह क्यों काम करता है: inject(:+)लेकिन यह नहीं है inject :+?
अर्नोल्ड रोआ

@AnnoldRoa "इंजेक्ट: +" मेरे लिए इसके काम करता है, आपको क्या परिणाम मिला?
गणेश सगरे


5

रूबी 2.4.0 जारी किया गया है, और इसमें एक Enumerable # योग विधि है। तो आप कर सकते हैं

array.sum

डॉक्स से उदाहरण:

{ 1 => 10, 2 => 20 }.sum {|k, v| k * v }  #=> 50
(1..10).sum                               #=> 55
(1..10).sum {|v| v * 2 }                  #=> 110

3

इसके लिए भी अनुमति देता है [1,2].sum{|x| x * 2 } == 6:

# http://madeofcode.com/posts/74-ruby-core-extension-array-sum
class Array
  def sum(method = nil, &block)
    if block_given?
      raise ArgumentError, "You cannot pass a block and a method!" if method
      inject(0) { |sum, i| sum + yield(i) }
    elsif method
      inject(0) { |sum, i| sum + i.send(method) }
    else
      inject(0) { |sum, i| sum + i }
    end
  end
end

3

शून्य मानों के साथ सरणी के लिए हम कॉम्पैक्ट कर सकते हैं और फिर राशि पूर्व इंजेक्षन कर सकते हैं-

a = [1,2,3,4,5,12,23.45,nil,23,nil]
puts a.compact.inject(:+)

2
array.reduce(:+)

के लिए काम करता सीमाओं की भी ... इसलिए,

(1..10).reduce(:+) returns 55

1

यदि आप गोल्फ महसूस करते हैं, तो आप कर सकते हैं

eval([123,321,12389]*?+)

यह एक स्ट्रिंग "123 + 321 + 12389" बनाएगा और फिर योग करने के लिए फ़ंक्शन इवल का उपयोग करेगा। यह केवल गोल्फिंग उद्देश्य के लिए है , आपको इसे उचित कोड में उपयोग नहीं करना चाहिए।


1

विधि 1:

    [1] pry(main)> [1,2,3,4].sum
    => 10
    [2] pry(main)> [].sum
    => 0
    [3] pry(main)> [1,2,3,5,nil].sum
    TypeError: nil can't be coerced into Integer

विधि 2:

   [24] pry(main)> [].inject(:+)
   => nil
   [25] pry(main)> [].inject(0, :+)
   => 0
   [4] pry(main)> [1,2,3,4,5].inject(0, :+)
   => 15
   [5] pry(main)> [1,2,3,4,nil].inject(0, :+)
   TypeError: nil can't be coerced into Integer
   from (pry):5:in `+'

विधि 3:

   [6] pry(main)> [1,2,3].reduce(:+)
   => 6
   [9] pry(main)> [].reduce(:+)
   => nil
   [7] pry(main)> [1,2,nil].reduce(:+)
   TypeError: nil can't be coerced into Integer
   from (pry):7:in `+'

विधि 4: जब सरणी में एक शून्य और रिक्त मान होते हैं, तो डिफ़ॉल्ट रूप से यदि आप उपरोक्त किसी भी कार्य का उपयोग करते हैं, तो राशि, योग, सब कुछ के माध्यम से इंजेक्ट करें।

TypeError: nil को Integer में coerced नहीं किया जा सकता है

आप इसे दूर कर सकते हैं,

   [16] pry(main)> sum = 0 
   => 0
   [17] pry(main)> [1,2,3,4,nil, ''].each{|a| sum+= a.to_i }
   => [1, 2, 3, 4, nil, ""]
   [18] pry(main)> sum
   => 10

विधि 6: eval

रूबी अभिव्यक्ति का मूल्यांकन स्ट्रिंग में।

  [26] pry(main)> a = [1,3,4,5]
  => [1, 3, 4, 5]
  [27] pry(main)> eval a.join '+'
  => 13
  [30] pry(main)> a = [1,3,4,5, nil]
  => [1, 3, 4, 5, nil]
  [31] pry(main)> eval a.join '+'
  SyntaxError: (eval):1: syntax error, unexpected end-of-input
  1+3+4+5+

1

3 तरीके से हम सरणी का योग कर सकते हैं

1) array.inject(0){|sum,x| sum + x }

2) array.inject('+')

3) array.join('+')


0

या आप इस विधि को आजमा सकते हैं:

def sum arr
  0 if arr.empty
  arr.inject :+
end


0
number = [1..100]

number. each do |n|

    final_number = n.sum

    puts "The sum is #{final_number}"
end

* इसने मेरे लिए एक नए डेवलपर के रूप में अच्छा काम किया। [] के भीतर मूल्यों को बदलकर आप अपनी संख्या सीमा को समायोजित कर सकते हैं



-8

आप .map और .sum का उपयोग कर सकते हैं :

array.map { |e| e }.sum

3
एक ही तत्व को वापस करने वाले मानचित्र का क्या मतलब है? यह ठीक उसी तरह है जैसेarray.sum
अर्नोल्ड रो

इसके अलावा array.sum माणिक में मौजूद नहीं है। माइक वुडहाउस का जवाब
उलसीसे बीएन

अब यह रूबी 2.4.0 में
स्थापित होता है
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.