একটি সি ++ ভেক্টরের উপাদানগুলি যোগ করতে কিভাবে?


240

একটিতে সমস্ত উপাদানের যোগফল খুঁজে পাওয়ার ভাল উপায়গুলি কী কী std::vector?

ধরুন এতে আমার std::vector<int> vectorকয়েকটি ভেক্টর রয়েছে যার মধ্যে কয়েকটি উপাদান রয়েছে। এখন আমি সমস্ত উপাদানগুলির যোগফল খুঁজতে চাই। একই জন্য বিভিন্ন উপায় কি?


1
"কতগুলো"? সত্যি? এটি একটি অত্যধিক অস্পষ্ট প্রশ্ন বলে মনে হচ্ছে। : p এটি করার জন্য একটি ভাল উপায় জিজ্ঞাসা করতে আরও দরকারী হতে পারে ।
জুলফ

3
যখন আপনি "অনুরূপ ফাংশন" বলছেন তখন আপনার অর্থ কী? আপনি কি std::accumulateবুস্টে প্রতিস্থাপনের সন্ধান করছেন ? (যদি তাই হয় তবে কেন?) আপনি কি এমন ফাংশন সন্ধান করছেন যা এর মতো কিছু করে std::accumulate? (যদি তা হয় তবে কী?)
জেমস ম্যাকনেলিস

4
আপনি যদি এর মতো কিছু std::accumulateচান তবে সম্ভবত আপনি এটিও কিছুটা আলাদা হতে চান (অন্যথায় আপনি কেবল ব্যবহার করতে পারেন std::accumulate); আপনি কোন পার্থক্য (গুলি) থেকে std::accumulateসন্ধান করছেন?
সিবি বেইলি

উত্তর:


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);

    গুরুত্বপূর্ণ দ্রষ্টব্য: শেষ যুক্তির ধরণটি কেবলমাত্র প্রাথমিক মানের জন্য নয়, ফলাফলের ধরণের জন্যও ব্যবহৃত হয় । আপনি যদি সেখানে কোনও int রাখেন তবে ভেক্টরটি ভাসমান অবস্থায় থাকলেও এটি ints জমে উঠবে। আপনি যদি ভাসমান-বিন্দু সংখ্যার যোগফল দিচ্ছেন, বা এটিকে পরিবর্তন 0করুন (নিউওনিকে ধন্যবাদ)। নীচে সি ++ 11 সমাধানও দেখুন।0.00.0f

সি ++ 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কোনও ফান্টারের সাহায্যে ব্যবহার করতে পারেন , এটি সি ++ 0 এক্স ল্যাম্বডা থেকে সংজ্ঞায়িত করতে কোডের আরও লাইন লাগে।
বেন ভয়েগট

8
আপনার ল্যাম্বদা উদাহরণগুলি কেন ব্যবহার করবেন for_each? accumulateআরও সংক্ষিপ্ত হবে (এমনকি এটি
ল্যাম্বদা

4
@ জাল্ফ: আপনার বক্তব্যটি সঠিক, আমার accumulateভিতরে থাকা উচিত ছিল for_eachতবে এই উদাহরণটি দরকারী নয় (শেখার উদ্দেশ্যে) কারণ এটি দেখায় যে আমরা লম্বা লম্বাও থাকতে পারি :-)
প্রসূন সৌরভ

58
সঙ্গে সাবধানaccumulate । শেষ যুক্তির ধরণটি কেবলমাত্র প্রাথমিক মানের জন্য নয়, ফলাফলের ধরণের জন্য ব্যবহৃত হয়। আপনি যদি intসেখানে রাখেন intতবে ভেক্টর থাকলেও এটি জমা হবে float। ফলাফলটি মোটামুটি ভুল হতে পারে এবং সংকলক আপনাকে কিছু না বলে ফলটিকে আবার ভাসিয়ে ফেলবে।
nneonneo

3
for_eachআপনার কাছে থাকলে আপনি কেন ব্যবহার করবেন accumulate?
juanchopanza

46

সবচেয়ে সহজ উপায় ব্যবহার করা std:accumuateএকটি এর vector<int> A:

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

34

প্রসূন ইতিমধ্যে এটি করার জন্য বিভিন্ন (এবং ভাল) উপায়ের হোস্ট অফার করেছে, যার কোনওটিরই এখানে পুনরাবৃত্তি করার প্রয়োজন নেই। আমি তবে গতির জন্য বিকল্প পদ্ধতির পরামর্শ দিতে চাই।

আপনি যদি এটি বেশ খানিকটা করতে চলেছেন তবে আপনি আপনার ভেক্টরকে "উপ-শ্রেণিবদ্ধকরণ" বিবেচনা করতে পারেন যাতে উপাদানগুলির যোগফল পৃথকভাবে বজায় থাকে ( আসলে উপ-শ্রেণিবদ্ধ ভেক্টর নয় যা কোনও অভাবের কারণে যথেষ্ট নয়) ভার্চুয়াল বিনাশকারী - আমি একটি বর্গ এটি মধ্যে সমষ্টি এবং একটি ভেক্টর রয়েছে, আরো কথা বলছি 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) না হয়ে বরং এটির মধ্যে একটি ভেক্টর বজায় রাখার মতো ভেক্টর হিসাবে একই পদ্ধতিতে আপনার নিজস্ব বর্গ তৈরি করতে পারতেন ।
paxdiablo


1
@ প্যাক্সিয়াব্লো আমি বিশ্বাস করি ডেভিডের অর্থ যদি ভেক্টরে সঞ্চিত ডেটা অপারেটর ব্যবহারের মাধ্যমে []] ব্যবহার করা হয় বা নন-কনস্ট্যান্ট ইটারেটরের মাধ্যমে পরোক্ষ করা হয়। ম্যানিপুলেটেড পজিশনে মানটি এখন আলাদা হবে যা যোগফলকে ভুল করে দেবে। যদি ক্লায়েন্ট কোড "সাবক্ল্যাসড" ভেক্টরের মধ্যে কোনও উপাদানের পরিবর্তিত রেফারেন্স ধরে রাখতে সক্ষম হয় তবে যোগফলটি সঠিক হওয়ার কোনও উপায় নেই।
ব্রেট কুহনস

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
এবং কেন মোড়ক অপারেটরের সাথে মোড়কের জন্য মুখ্য সংখ্যা যুক্ত করে ভেক্টর দিয়ে চক্রটি কেন নয়? :-)
প্যাক্সিডিয়াবল

3
@ প্যাক্সিডিয়াবলো আপনার কেবলমাত্র অপেক্ষাকৃত প্রধান হতে হবে v.size()
clstrfsck

1
-1: ভেক্টর :: আকার () একটি স্বাক্ষরবিহীন মান প্রদান করে, (v.size () - 1) সতর্কতা উত্পন্ন করে বা খারাপ ক্ষেত্রে মাইনফিল্ড তৈরি করে।
জুলিয়েন গের্টল্ট

1
কেন এই উত্তর বিদ্যমান? পিছনের দিকের যোগফলের কোনও সুবিধা রয়েছে, বা আপনি কেবল ট্রোলিং করছেন?
লিন

4
@ লিন: যদি ভেক্টরের শেষটি ক্যাশে গরম থাকে (পূর্ববর্তী লুপ থেকে যে এগিয়ে গেছে) তবে হ্যাঁ, পিছনের দিকে লুপ করা বর্তমান ইন্টেল x86 সিপিইউগুলিতে পরিমাপযোগ্যভাবে দ্রুততর হতে পারে। এছাড়াও, শূন্যের নিচে একটি লুপ-কাউন্টার গণনা করাকে সংকলকটি asm এর একটি নির্দেশিকা সংরক্ষণ করতে পারে, এটি লুপটিকে আনরোল না করলে তা উল্লেখযোগ্য হতে পারে। সামনের দিকে লুপ করার সময় প্রিফেচিং কখনও কখনও কিছুটা ভাল কাজ করে, তবে সাধারণভাবে সর্বদা পিছনের দিকে লুপ করা ভাল নয়।
পিটার কর্ডস

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

উত্তর করার জন্য ধন্যবাদ. বিটিডাব্লু: স্ট্যান্ড :: জমে ও বাড়াতে :: সময়ের জটিলতায় জমা করার মধ্যে পার্থক্য কী?
প্রসূন সৌরভ

1
সময় জটিলতা স্ট্যান্ড এবং বুস্টের জমা - লিনিয়ারের জন্য একই। এক্ষেত্রে বুস্ট :: জোগানো টাইপ করা সহজ এবং ম্যানুয়ালি শেষের চেয়ে প্রেরণের চেয়ে সহজ। কোন বাস্তব পার্থক্য আছে।
ধাতু

7
boost::accumulateচারদিকে কেবল একটি মোড়ক std::accumulate
রাফাক

2
অ-বৃদ্ধির উপায়টি খুব বেশি শক্ত নয়: #include <numeric>এবং std::accumulate(v.begin(), v.end(), (int64_t)0);। লক্ষ্য করুন যে প্রারম্ভিক সংগ্রহকারী মানটির প্রকারটি সঞ্চয়ের প্রকার হিসাবে ব্যবহৃত হয়, তাই আপনি যদি 64৪-বিটের ফলাফলের মধ্যে 8-বিট উপাদান যোগ করতে চান তবে আপনি এটি করেন।
পিটার কর্ডেস

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

কেবল সি ++ 0x:

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

এটি অন্য কোথাও উল্লিখিত BOOST_FOREach এর মতো এবং আরও জটিল পরিস্থিতিতে স্পষ্টতার একই সুবিধা রয়েছে, জমে থাকা বা ফোর_আচের সাথে ব্যবহৃত রাষ্ট্রীয় ফান্টারের তুলনায়।


3
আপনি যদি এতে পরিবর্তন for (int n : v) sum += n;করেন for (auto n : v) sum += n;তবে কোনও ভেক্টর টেম্পলেট দিয়ে কাজ করবে। আমি ওপিকে ভেক্টর রেফার্স জানতাম <int>, তবে এই উপায়ে কিছুটা সাধারণ :-)
জোনাস

5

আমি পার্ল ব্যবহারকারী, আমাদের কাছে একটি গেমটি একটি ভেরিয়েবলকে বাড়ানোর প্রতিটি বিভিন্ন উপায় খুঁজে পাওয়া ... এটি এখানে আসলে আলাদা নয়। সি ++ তে কোনও ভেক্টরের উপাদানগুলির যোগফল কতটি উপায়ের উত্তর সম্ভবত an infinity...

আমার 2 সেন্ট:

কুরুচিপূর্ণ পুনরুক্তি বাক্য বিন্যাস মুক্ত করতে 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();
}

আপনি কেন বলছেন যে সূচকগুলিতে পুনরাবৃত্তি করা অযোগ্য? এটা বলার জন্য আপনার ভিত্তি কী?
বোবোবোলো

@ বোবোবো: ভাল, অকার্যকর সম্ভবত খুব বেশি। আপনার ভেক্টর এবং ইনক্রিমেন্ট কাউন্টার থেকে কার্যকর ডেটা অবস্থান গণনা করার জন্য উভয়ই রয়েছে তবে এই দুটি ক্রিয়াকলাপের মধ্যে একটি পর্যাপ্ত হওয়া উচিত, তবে পুনরুক্তি পুনরাবৃত্তকারীগুলির ব্যয় আরও খারাপ হতে পারে। সুতরাং আমি শব্দটি মুছে ফেলব।
ক্রিসস

একটি অনুকূলকরণ সংকলক সূচক ভেরিয়েবলটিকে অপ্টিমাইজ করতে পারে এবং যদি এটি চায় তবে কেবলমাত্র পয়েন্টার বৃদ্ধি ব্যবহার করতে পারে। (এটি লুপ-প্রস্থান শর্তটিকে পয়েন্টারের তুলনায় তুলনায় পরিণত করতে পারে 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 দিয়ে আরম্ভ করা হয়েছে I আমি অ্যারের মতো একটি সাধারণ লুপ দিয়ে যোগফলটি গণনা করেছি।


1
intসূচকে একটি ব্যবহার করা std::vectorসাধারণভাবে নিরাপদ নয়। v.size()সঞ্চিত হওয়া সর্বোচ্চ মানের চেয়ে বড় হতে পারে int(লক্ষ্য করুন যে কয়েকটি টার্গেট প্ল্যাটফর্ম এবং সংকলক সহ, size_of(int) < size_of(size_t))। এই ক্ষেত্রে, আপনার কোড সূচকে উপচে পড়বে। স্টাড :: ভেক্টর <টি> :: আকার_প্রকার পছন্দ করা উচিত।
ভিনসেন্ট শ্যালো-লেবার্ড

এটি একটি উদাহরণ @ ভিনসেন্টসালিউ-ল্যাবোর্ড আপনি ডেটা টাইপ নিতে পারেন এবং এটি আপনার প্রয়োজন অনুসারে আকার।
রবি কুমার যাদব

-5

এটা সহজ. সি ++ 11 কোনও ভেক্টরের উপাদানগুলি যোগ করতে একটি সহজ উপায় সরবরাহ করে।

sum = 0; 
vector<int> vec = {1,2,3,4,5,....}
for(auto i:vec) 
   sum+=i;
cout<<" The sum is :: "<<sum<<endl; 
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.