लूप के बिना C++ में वेक्टर इंट के वेक्टर को कैसे योग करें




stdvector (5)

मैं एक गैर-लूप तरीके से vector<vector<int>> सभी तत्वों vector<vector<int>> को लागू करने का प्रयास करता हूं।
मैंने पहले कुछ प्रासंगिक प्रश्नों की जाँच की है, C ++ वेक्टर के तत्वों को कैसे योग करें?
इसलिए मैं std::accumulate का उपयोग करने की कोशिश करता हूं std::accumulate इसे लागू करने के लिए std::accumulate करें लेकिन मुझे लगता है कि मेरे लिए std::accumulate में एक Binary Operator को अधिभार देना मुश्किल है std::accumulate इसे std::accumulate और कार्यान्वित करना।
तो मैं उलझन में हूं कि इसे std::accumulate साथ कैसे लागू किया जाए std::accumulate या कोई बेहतर तरीका है?
अगर मन नहीं होता तो कोई मेरी मदद कर सकता था?
अग्रिम में धन्यवाद।


आपको std::accumulate का उपयोग करने की आवश्यकता है std::accumulate एक द्विआधारी ऑपरेटर के साथ बाहरी vector लिए एक बार दो बार std::accumulate , जो जानता है कि std::accumulate लिए एक अतिरिक्त कॉल का उपयोग करके आंतरिक vector को कैसे योग करना है std::accumulate :

int sum = std::accumulate(
    vec.begin(), vec.end(),                       // iterators for the outer vector
    0,                                            // initial value for summation - 0
    [](int init, const std::vector<int>& intvec){ // binaryOp that sums a single vector<int>
        return std::accumulate(
            intvec.begin(), intvec.end(), // iterators for the inner vector
            init);                        // current sum
                                          // use the default binaryOp here
    }
);

इस मामले में, मैं std::accumulate का उपयोग करने का सुझाव नहीं देता हूं std::accumulate क्योंकि यह पठनीयता को बहुत कम कर देगा। इसके अलावा, यह फ़ंक्शन आंतरिक रूप से छोरों का उपयोग करता है, इसलिए आप कुछ भी नहीं बचाएंगे। निम्नलिखित लूप-आधारित समाधान की तुलना अन्य उत्तरों के साथ करें जो std::accumulate उपयोग करते हैं std::accumulate :

int result = 0 ;
for (auto const & subvector : your_vector)
    for (int element : subvector)
        result += element;

क्या पुनरावृत्तियों, एसटीएल फ़ंक्शंस और लैम्ब्डा फ़ंक्शंस के संयोजन का उपयोग करने से आपके कोड को समझना और तेज करना आसान हो जाता है? मेरे लिए, उत्तर स्पष्ट है। लूप्स बुराई नहीं हैं, खासकर ऐसे सरल अनुप्रयोग के लिए।


छोरों से बचने के लिए, आपको विशेष रूप से प्रत्येक तत्व जोड़ना होगा:

std::vector<int> database = {1, 2, 3, 4};
int sum = 0;
int index = 0;
// Start the accumulation
sum = database[index++];
sum = database[index++];
sum = database[index++];
sum = database[index++];

इस बात की कोई गारंटी नहीं है कि std::accumulate गैर-लूप (नो लूप) होगा। यदि आपको छोरों से बचने की आवश्यकता है, तो इसका उपयोग न करें।

IMHO, लूप का उपयोग करने के साथ कुछ भी गलत नहीं है: के for , while या do-while । समरूप सरणियों के लिए विशेष निर्देश रखने वाले प्रोसेसर लूप का उपयोग करते हैं। कोड स्थान के संरक्षण के लिए लूप एक सुविधाजनक विधि है। हालांकि, ऐसे समय हो सकते हैं जब लूप अनियंत्रित होना चाहते हैं (प्रदर्शन कारणों से)। आपके पास इसमें विस्तारित या अनियंत्रित सामग्री के साथ एक लूप हो सकता है।


https://en.cppreference.com/w/cpp/algorithm/accumulate अनुसार, ऐसा लगता है कि बाइनरीऑप के बाएं हाथ पर वर्तमान राशि है, और दाईं ओर अगला श्रेणी तत्व है। तो आपको std चलाना चाहिए :: दाहिने हाथ की ओर तर्क पर संचय करें, और फिर इसे बाएं हाथ के तर्क के साथ योग करें और परिणाम वापस करें। यदि आप C ++ 14 या उसके बाद का उपयोग करते हैं,

auto binary_op = [&](auto cur_sum, const auto& el){
    auto rhs_sum = std::accumulate(el.begin(), el.end(), 0);
    return cur_sum + rhs_sum;
};

मैंने हालांकि कोड को संकलित करने की कोशिश नहीं की :)। अगर मैंने तर्कों के क्रम को गड़बड़ कर दिया, तो उन्हें बदल दें।

संपादित करें: गलत शब्दावली - आप बाइनरीओप को अधिभार नहीं देते हैं, आप इसे पास करते हैं।


std::accumulate हस्ताक्षर std::accumulate है:

T accumulate( InputIt first, InputIt last, T init,
              BinaryOperation op );

ध्यान दें कि रिटर्न मान init पैरामीटर से घटाया गया है (यह जरूरी नहीं है कि यह value_type का InputIt )।

बाइनरी ऑपरेशन है:

Ret binary_op(const Type1 &a, const Type2 &b);

कहाँ ... ( https://en.cppreference.com/w/cpp/algorithm/accumulate ) ...

टाइप Type1 का प्रकार ऐसा होना चाहिए कि टाइप T की वस्तु को स्पष्ट रूप से Type1 परिवर्तित किया जा सके। Type2 टाइप ऐसा होना चाहिए कि InputIt टाइप की वस्तु को InputIt जा सके और फिर टाइप InputIt बदल दिया जाए। टाइप Ret होना आवश्यक है कि टाइप T का एक ऑब्जेक्ट टाइप Ret का मान नियत किया जा सकता है।

हालाँकि, जब T value_type की InputIt , तो उपरोक्त सरल है और आपके पास है:

using value_type = std::iterator_traits<InputIt>::value_type;
T binary_op(T,value_type&).

आपका अंतिम परिणाम एक int माना जाता है, इसलिए T int । आपको दो कॉल की जरूरत है दो std::accumulate value_type == std::vector<int> , एक बाहरी वेक्टर के लिए (जहां value_type == std::vector<int> ) और एक आंतरिक वैक्टर के लिए (जहां value_type == int ):

#include <iostream>
#include <numeric>
#include <iterator>
#include <vector>

template <typename IT, typename T>
T accumulate2d(IT outer_begin, IT outer_end,const T& init){
    using value_type = typename std::iterator_traits<IT>::value_type;
    return std::accumulate( outer_begin,outer_end,init,
        [](T accu,const value_type& inner){
            return std::accumulate( inner.begin(),inner.end(),accu);
        });
}

int main() {
    std::vector<std::vector<int>> x{ {1,2} , {1,2,3} };
    std::cout << accumulate2d(x.begin(),x.end(),0);
}





stdvector