C ++ वेक्टर के तत्वों को कैसे योग करें?


240

सभी तत्वों के योग को खोजने के अच्छे तरीके क्या हैं std::vector?

मान लीजिए कि मेरे पास std::vector<int> vectorकुछ तत्वों के साथ एक वेक्टर है। अब मैं सभी तत्वों का योग खोजना चाहता हूं। उसी के लिए अलग-अलग तरीके क्या हैं?


1
"कितने"? वास्तव में? यह एक अत्यधिक अस्पष्ट सवाल लगता है। : पी यह करने के लिए एक अच्छा तरीका पूछने के लिए अधिक उपयोगी हो सकता है।
जुलफ

3
जब आप कहते हैं "क्या मतलब है?" क्या आप std::accumulateबूस्ट में प्रतिस्थापन के लिए देख रहे हैं ? (यदि हां, तो क्यों?) क्या आप उन कार्यों की तलाश कर रहे हैं जो कुछ इसी तरह का काम करते हैं std::accumulate? (यदि हां, तो क्या?)
जेम्स मैकनेलिस

4
यदि आप कुछ ऐसा ही चाहते हैं std::accumulate, तो संभवतः आप यह भी चाहते हैं कि यह कुछ मामलों में अलग हो (अन्यथा आप बस उपयोग कर सकते हैं std::accumulate); क्या अंतर है std::accumulate?
CB बेली

जवाबों:


429

दरअसल काफी तरीके हैं।

int sum_of_elems = 0;

सी ++ 03

  1. पाश के लिए क्लासिक:

    for(std::vector<int>::iterator it = vector.begin(); it != vector.end(); ++it)
        sum_of_elems += *it;
  2. एक मानक एल्गोरिथ्म का उपयोग करना:

    #include <numeric>
    
    sum_of_elems = std::accumulate(vector.begin(), vector.end(), 0);

    महत्वपूर्ण नोट: अंतिम तर्क का प्रकार न केवल प्रारंभिक मूल्य के लिए उपयोग किया जाता है, बल्कि परिणाम के प्रकार के लिए भी। यदि आप वहाँ एक इंट डालते हैं, तो यह वेक्टर भी तैरता है, भले ही उसमें स्याही जमा हो जाए। आप फ्लोटिंग प्वाइंट नंबर, परिवर्तन संक्षेप रहे हैं 0करने के लिए 0.0या 0.0f(nneonneo करने के लिए धन्यवाद)। नीचे C ++ 11 समाधान भी देखें।

C ++ 11 और उच्चतर

  1. ख। भविष्य के परिवर्तनों के मामले में भी वेक्टर प्रकार का ध्यान रखना

    #include <numeric>
    
    sum_of_elems = std::accumulate(vector.begin(), vector.end(),
                                   decltype(vector)::value_type(0));
  2. का उपयोग कर std::for_each:

    std::for_each(vector.begin(), vector.end(), [&] (int n) {
        sum_of_elems += n;
    });
  3. लूप के लिए रेंज-आधारित का उपयोग करना (रोजर पाटे के लिए धन्यवाद):

    for (auto& n : vector)
        sum_of_elems += n;

6
बेशक C ++ 03 में आप std::for_eachएक फ़नकार के साथ उपयोग कर सकते हैं , यह कोड की अधिक पंक्तियों को C ++ 0x लैम्ब्डा की तुलना में परिभाषित करता है।
बेन वोइगट

8
आपके लंबोदर उदाहरणों का उपयोग क्यों करते हैं for_each? accumulateअधिक संक्षिप्त होगा (यह लैम्ब्डा की जरूरत नहीं है, भले ही)
jalf

4
@ जैलफ: आपकी बात सही है, मुझे accumulateअंदर का उपयोग करना चाहिए था, for_eachलेकिन यह उदाहरण उपयोगी नहीं है (सीखने के उद्देश्य से) क्योंकि यह दर्शाता है कि हमारे पास नेम्बडास भी हो सकता है :-)
प्रसून सौरव

58
सावधान रहो के साथ accumulate। अंतिम तर्क के प्रकार का उपयोग केवल प्रारंभिक मूल्य के लिए नहीं किया जाता है, बल्कि परिणाम के प्रकार के लिए किया जाता है। यदि आप intवहां डालते हैं, intतो यह वेक्टर के होने पर भी जमा होगा float। परिणाम आसानी से गलत हो सकता है, और संकलक आपको बताए बिना एक फ्लोट तक परिणाम कास्ट करेगा।
nnonneo

3
for_eachअगर आपके पास है तो आप क्यों इस्तेमाल करेंगे accumulate?
जुआनकोपंजा

46

सबसे आसान तरीका उपयोग करने के लिए है std:accumuateएक की vector<int> A:

#include <numeric>
cout << accumulate(A.begin(), A.end(), 0);

34

प्रसून ने ऐसा करने के लिए पहले से ही विभिन्न (और अच्छे) तरीकों की मेजबानी पेश की है, जिनमें से किसी को भी यहां दोहराने की आवश्यकता नहीं है। मैं हालांकि गति के लिए एक वैकल्पिक दृष्टिकोण का सुझाव देना चाहूंगा।

यदि आप इसे बहुत कम करने जा रहे हैं, तो आप अपने वेक्टर को "सब-क्लासिंग" पर विचार करना चाह सकते हैं ताकि तत्वों का एक योग अलग से बना रहे (न कि वास्तव में सब-क्लासिंग वेक्टर, जो एक की कमी के कारण iffy है वर्चुअल डिस्ट्रॉक्टर - मैं एक ऐसे वर्ग के बारे में बात कर रहा हूं, जिसमें योग और उसके भीतर एक सदिश होता है, has-aबल्कि is-aसदिश-जैसे तरीके प्रदान करता है)।

एक खाली वेक्टर के लिए, योग शून्य पर सेट है। वेक्टर के हर प्रविष्टि पर, राशि में सम्मिलित किया जा रहा तत्व जोड़ें। प्रत्येक विलोपन पर, इसे घटाएं। मूल रूप से, कुछ भी जो अंतर्निहित वेक्टर को बदल सकता है, यह सुनिश्चित करने के लिए इंटरसेप्ट किया जाता है कि राशि को सुसंगत रखा गया है।

इस तरह, आपके पास समय पर किसी भी बिंदु पर राशि की "गणना" करने के लिए एक बहुत ही कुशल ओ (1) तरीका है (बस गणना की गई राशि वापस लौटाएं)। सम्मिलन और विलोपन आपको कुल समायोजित करने में थोड़ा अधिक समय लगेगा और आपको इस प्रदर्शन को ध्यान में रखना चाहिए।

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

कुछ इस तरह होगा:

class UberVector:
    private Vector<int> vec
    private int sum

    public UberVector():
        vec = new Vector<int>()
        sum = 0

    public getSum():
        return sum

    public add (int val):
        rc = vec.add (val)
        if rc == OK:
            sum = sum + val
        return rc

    public delindex (int idx):
        val = 0
        if idx >= 0 and idx < vec.size:
            val = vec[idx]
        rc =  vec.delindex (idx)
        if rc == OK:
            sum = sum - val
        return rc

जाहिर है, यह छद्म कोड है और आप थोड़ी अधिक कार्यक्षमता रखना चाहते हैं, लेकिन यह मूल अवधारणा को दर्शाता है।


7
दिलचस्प है, लेकिन सावधान रहें क्योंकि std::vectorउपवर्ग के लिए इसका मतलब नहीं है।
इवान टेरान

7
क्षमा करें, मुझे स्पष्ट होना चाहिए था - आप अपनी खुद की कक्षा को वेक्टर के समान तरीके से बना सकते हैं, जो has-aएक उचित उपवर्ग ( is-a) होने के बजाय उसके भीतर एक वेक्टर बनाए रखता है ।
पैक्सडीब्लो

1
यह समस्याग्रस्त है जब तक कि आप डेटा में operator[](int)
एक्सेसर्स को

1
@paxdiablo मेरा मानना ​​है कि डेविड का अर्थ है यदि वेक्टर में संग्रहीत डेटा को ऑपरेटर के उपयोग के माध्यम से हेरफेर किया जाता है [] या एक गैर-कास्ट इट्रेटर के माध्यम से अप्रत्यक्ष। जोड़-तोड़ की स्थिति का मूल्य अब अलग होगा जो योग को गलत बना देगा। यदि ग्राहक कोड कभी भी "उप-वर्ग" वेक्टर के भीतर किसी भी तत्व के लिए एक परस्पर संदर्भ रखने में सक्षम है, तो राशि को आश्वस्त करने का कोई तरीका नहीं है।
ब्रेट कुहन्स

2
यह दृष्टिकोण मूल वेक्टर संचालन के लिए प्रदर्शन दंड का कारण बनता है।
बसिलेव्स

23

जब आप इसे पीछे की ओर कर सकते हैं तो आगे के लिए योग क्यों करें ? दिया हुआ:

std::vector<int> v;     // vector to be summed
int sum_of_elements(0); // result of the summation

हम सबस्क्रिप्टिंग का उपयोग कर सकते हैं, पीछे की ओर गिनती:

for (int i(v.size()); i > 0; --i)
    sum_of_elements += v[i-1];

हम श्रेणी-चेक किए गए "सबस्क्रिप्टिंग" का उपयोग कर सकते हैं, "पीछे की ओर गिनना" (बस मामले में):

for (int i(v.size()); i > 0; --i)
    sum_of_elements += v.at(i-1);

हम एक लूप में रिवर्स पुनरावृत्तियों का उपयोग कर सकते हैं:

for(std::vector<int>::const_reverse_iterator i(v.rbegin()); i != v.rend(); ++i)
    sum_of_elements += *i;

हम आगे पुनरावृत्तियों का उपयोग कर सकते हैं, पीछे की ओर घूमते हुए, लूप (ऊह, मुश्किल!) के लिए।

for(std::vector<int>::const_iterator i(v.end()); i != v.begin(); --i)
    sum_of_elements += *(i - 1);

हम accumulateरिवर्स पुनरावृत्तियों के साथ उपयोग कर सकते हैं :

sum_of_elems = std::accumulate(v.rbegin(), v.rend(), 0);

हम for_eachरिवर्स लेटर्स का उपयोग करते हुए लैम्बडा एक्सप्रेशन के साथ उपयोग कर सकते हैं :

std::for_each(v.rbegin(), v.rend(), [&](int n) { sum_of_elements += n; });

तो, जैसा कि आप देख सकते हैं, वेक्टर पीछे की ओर योग करने के कई तरीके हैं जैसे कि वेक्टर आगे की ओर योग हैं, और इनमें से कुछ बहुत अधिक रोमांचक हैं और ऑफ-बाय-वन त्रुटियों के लिए अधिक से अधिक अवसर प्रदान करते हैं।


36
और रैपराउंड के लिए मापांक ऑपरेटर के साथ एक प्रमुख संख्या जोड़कर वेक्टर के माध्यम से भी चक्र क्यों नहीं? :-)
paxdiablo

3
@paxdiablo आपको केवल वास्तव में अपेक्षाकृत प्रधान होने की आवश्यकता है v.size()
क्लेस्ट्रॉस्क

1
-1: वेक्टर :: आकार () एक अहस्ताक्षरित मान लौटाता है, (v.size () - 1) जैसे भाव उत्पन्न करता है, या बुरे मामलों में एक खान क्षेत्र उत्पन्न करता है।
जुलिएन गुर्टाल्ट

1
यह उत्तर क्यों मौजूद है? क्या पीछे की ओर योग करने का एक फायदा है, या आप बस ट्रोलिंग कर रहे हैं?
लिन

4
@ लियन: यदि वेक्टर का अंत कैश में गर्म होता है (पिछले लूप से जो आगे की तरफ चला जाता है), तो हाँ, पीछे की तरफ लूपिंग करना मौजूदा इंटेल x86 सीपीयू पर तेजी से कम हो सकता है। इसके अलावा, लूप-काउंटर को शून्य तक गिनने से कंपाइलर को निर्देश दिया जा सकता है कि यह लूप को अनियंत्रित नहीं करता है, जो महत्वपूर्ण हो सकता है। प्रीफ़ेटिंग कभी-कभी थोड़ा बेहतर काम करता है जब आगे की तरफ लूपिंग होता है, हालांकि, इसलिए सामान्य तौर पर हमेशा पीछे की तरफ लूप करना बेहतर नहीं होता है।
पीटर कॉर्डेस

15
#include<boost/range/numeric.hpp>
int sum = boost::accumulate(vector, 0);

जवाब के लिए धन्यवाद। BTW एसटीडी के बीच अंतर क्या है :: संचय और बढ़ावा :: समय जटिलता में जमा?
प्रसून सौरव

1
समय की जटिलता एसटीडी और बढ़ावा के संचय के लिए समान है - रैखिक। इस मामले में, बढ़ावा :: संचय शुरू और अंत में मैन्युअल रूप से भेजने की तुलना में टाइप करना आसान है। कोई वास्तविक अंतर नहीं है।
धातु

7
boost::accumulateचारों ओर एक आवरण है std::accumulate
रफाक

2
गैर-बढ़ावा तरीका बहुत कठिन नहीं है: #include <numeric>और std::accumulate(v.begin(), v.end(), (int64_t)0);। ध्यान दें कि प्रारंभिक संचयकर्ता के प्रकार का उपयोग संचायक प्रकार के रूप में किया जाता है, इसलिए यदि आप 8-बिट तत्वों को 64-बिट परिणाम में जोड़ना चाहते हैं, तो आप इसे कैसे करते हैं।
पीटर कॉर्ड्स

6

एक भी std::valarray<T>इस तरह का उपयोग कर सकते हैं

#include<iostream>
#include<vector>
#include<valarray>

int main()
{
    std::vector<int> seq{ 1,2,3,4,5,6,7,8,9,10 };
    std::valarray<int> seq_add{ seq.data(), seq.size() };
    std::cout << "sum = " << seq_add.sum() << "\n";

    return 0;
}

कुछ इस तरह से कुशल नहीं हो सकते हैं क्योंकि valarrayजरूरतों का आकार वेक्टर के आकार जितना बड़ा होना चाहिए और इसे शुरू करने valarrayमें भी समय लगेगा।

उस स्थिति में, इसका उपयोग न करें और इसे अनुक्रम को समेटने का एक और तरीका मान लें।


5

C ++ 0x केवल:

vector<int> v; // and fill with data
int sum {}; // or = 0 ... :)
for (int n : v) sum += n;

यह अन्यत्र उल्लिखित BOOST_FOREACH के समान है और संचय या for_each के साथ उपयोग किए जाने वाले स्टेटफुल फ़ंक्शनलर्स की तुलना में अधिक जटिल स्थितियों में स्पष्टता का समान लाभ है।


3
आप को बदलते हैं for (int n : v) sum += n;में for (auto n : v) sum += n;यह किसी भी वेक्टर टेम्पलेट के साथ काम करेंगे। मैं जानता हूं कि ओपी वेक्टर <int> का उल्लेख करता है, लेकिन यह तरीका थोड़ा अधिक सामान्य है :-)
जोनास

5

मैं एक पर्ल उपयोगकर्ता हूं, एक ऐसा गेम जो हमारे पास है कि किसी भिन्न को बढ़ाने के लिए हर अलग-अलग तरीके ढूंढे जाएं ... यह वास्तव में यहां अलग नहीं है। C ++ में सदिश के तत्वों का योग ज्ञात करने के कितने तरीकों का उत्तर शायद an infinity...

मेरे 2 सेंट:

बदसूरत itter सिंटैक्स से मुक्त होने के लिए BOOST_FOREACH का उपयोग करना:

sum = 0;
BOOST_FOREACH(int & x, myvector){
  sum += x;
}

सूचकांकों पर पुनरावृत्ति (वास्तव में पढ़ने में आसान)।

int i, sum = 0;
for (i=0; i<myvector.size(); i++){
  sum += myvector[i];
}

यह एक विनाशकारी है, एक स्टैक की तरह वेक्टर तक पहुंचना:

while (!myvector.empty()){
   sum+=myvector.back();
   myvector.pop_back();
}

आप यह क्यों कहते हैं कि सूचकांकों पर चलना अक्षम है? आपके कहने का आधार क्या है?
बोबोबोबो

@bobobobo: ठीक है, अयोग्य शायद अत्यधिक है। आपके पास वेक्टर और इंक्रीमेंट काउंटर से प्रभावी डेटा स्थिति की गणना करने के लिए दोनों हैं लेकिन इन दोनों में से एक ऑपरेशन पर्याप्त होना चाहिए, लेकिन डेरीफेरिंग iterators की लागत और भी खराब हो सकती है। इसलिए मैं शब्द को हटा दूंगा।
क्रि।

एक अनुकूलन करने वाला कंपाइलर इंडेक्स वेरिएबल को ऑप्टिमाइज़ कर सकता है और यदि वह चाहे तो एक पॉइंटर इन्क्रीमेंट का उपयोग कर सकता है। (यह लूप-एग्जिट कंडीशन को पॉइंटर-तुलना के खिलाफ बना सकता है start + length)। वास्तविक पुनरावृत्तियों को भी पूरी तरह से अनुकूलित करना चाहिए। याद रखें, यह बुरा नहीं है; यह पूरी तरह से asm के लिए संकलित है, व्याख्या नहीं की गई है।
पीटर कॉर्डेस

-1

मैंने एक वेक्टर के सभी तत्वों का योग खोजने का सबसे आसान तरीका पाया

#include <iostream>
#include<vector>
using namespace std;

int main()
{
    vector<int>v(10,1);
    int sum=0;
    for(int i=0;i<v.size();i++)
    {
        sum+=v[i];
    }
    cout<<sum<<endl;

}

इस कार्यक्रम में, मेरे पास 10 आकार का एक वेक्टर है और 1. द्वारा आरंभीकृत किया गया है। मैंने सरणी में एक साधारण लूप द्वारा योग की गणना की है।


1
intसूचकांक का उपयोग करना std::vectorसामान्य रूप से सुरक्षित नहीं है। v.size()उच्चतम मूल्य से बड़ा हो सकता है जिसे int(कुछ लक्ष्य प्लेटफार्मों और संकलक के साथ ध्यान दें) में संग्रहीत किया जा सकता है size_of(int) < size_of(size_t)। इस स्थिति में, आपका कोड इंडेक्स को ओवरफ्लो कर देगा। std :: वेक्टर <T> :: size_type को प्राथमिकता दी जानी चाहिए।
विंसेंट सौल्यू-लेबोर्डे

यह एक उदाहरण है @ VincentSaulue-Laborde आप डेटा प्रकार ले सकते हैं और यह आपकी आवश्यकता के अनुसार आकार है।
रवि कुमार यादव

-5

यह आसान है। C ++ 11 एक वेक्टर के तत्वों को योग करने का एक आसान तरीका प्रदान करता है।

sum = 0; 
vector<int> vec = {1,2,3,4,5,....}
for(auto i:vec) 
   sum+=i;
cout<<" The sum is :: "<<sum<<endl; 
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.