दो std :: वैक्टरों को जोड़ना

मैं दो std :: vector s को कैसे जोड़ूं?

469
@lecaruyer आप महसूस करते हैं कि आपने अभी एक प्रश्न चिह्नित किया है जिसे डुप्लिकेट के रूप में दो साल पहले पूछा गया था
जोड़ा लेखक eshirima, स्रोत
@FauChristian: नहीं, दक्षता के दृष्टिकोण से उपयोग नहीं किया जा सकता है। वेक्टर स्मृति निरंतर होना चाहिए, इसलिए आपको जो सुझाव दिया गया है वह असंभव है। यदि आप "नोड्स के प्रबंधन के कुछ परिष्कृत साझाकरण" चाहते थे, और यदि आप वेक्टर वर्ग को इस तरह से बदलना चाहते थे, तो आप एक डेक के साथ समाप्त हो जाएंगे। फिर भी सुझाव दिया गया है कि स्मृति में पुन: उपयोग करना बहुत मुश्किल है, यद्यपि यह थोड़ा और व्यवहार्य होना शुरू हो जाएगा। मुझे नहीं लगता कि यह वर्तमान में लागू किया गया है। मुख्य बात यह है कि प्रबंधन नोड्स (एक डेक) के इस तरह के साझाकरण में अंत नोड आंशिक रूप से खाली हो सकता है।
जोड़ा लेखक Cookie, स्रोत
दिए गए उत्तरों वास्तव में concatenate नहीं है। वे एक प्रति संलग्न करते हैं। एक std :: वेक्टर concatenate विधि बनाने के लिए एक उपयोग (दक्षता के दृष्टिकोण के लिए) का उपयोग किया जा सकता है, हालांकि इसे नोड्स के प्रबंधन के कुछ परिष्कृत साझाकरण की आवश्यकता होगी और शायद यही कारण नहीं है।
जोड़ा लेखक FauChristian, स्रोत
क्या मैं अकेला सोच रहा हूं कि यह मानक पुस्तकालय में a + b या a.concat (b) के रूप में क्यों लागू नहीं किया गया है? हो सकता है कि डिफ़ॉल्ट कार्यान्वयन उप-शीर्ष होगा, लेकिन प्रत्येक सरणी संगतता को माइक्रो-अनुकूलित करने की आवश्यकता नहीं है
जोड़ा लेखक oseiskar, स्रोत

16 उत्तर

vector1.insert( vector1.end(), vector2.begin(), vector2.end() );
531
जोड़ा
यदि आप एक से कई वैक्टरों को जोड़ रहे हैं, तो क्या पहले गंतव्य वेक्टर पर reserve को कॉल करना सहायक होता है?
जोड़ा लेखक Faheem Mitha, स्रोत
@ एडिन मैं देखता हूँ। स्पष्टीकरण के लिए धन्यवाद।
जोड़ा लेखक Faheem Mitha, स्रोत
@ खौरा: यह उस बिंदु से डरावना है जिस पर विश्वास करना मुश्किल है। इटरेटर का पता लगाने के लिए कार्यान्वयन के लिए यह बहुत छोटा है यादृच्छिक अभिगम, आकार की गणना, और आवश्यक स्थान को पूर्व-आरक्षित करना। मुझे लगता है कि एमएसएफटी भी आगे इटरेटर के लिए करता है।
जोड़ा लेखक Mooing Duck, स्रोत
@AlexanderRafferty: केवल तभी vector1.capacity ()> = 2 * vector1.size() । जो तब तक अटूट है जब तक आप std :: vector :: reserve() कहलाते हैं। अन्यथा वेक्टर पुन: आवंटित करेंगे, पैरामीटर 2 और 3 के रूप में पारित इटरेटर्स को अमान्य कर देगा।
जोड़ा लेखक Drew Dormann, स्रोत
मेरा एक सवाल है। क्या यह काम करेगा यदि वेक्टर 1 और वेक्टर 2 एक ही वैक्टर हैं?
जोड़ा लेखक Alexander Rafferty, स्रोत
मैं केवल प्रत्येक वेक्टर धारण करने वाले तत्वों की संख्या प्राप्त करने के लिए कोड जोड़ता हूं, और वेक्टर 1 को सबसे बड़ा रखने वाला व्यक्ति सेट करता हूं। यदि आप अन्यथा ऐसा करते हैं तो आप बहुत अनावश्यक प्रतिलिपि कर रहे हैं।
जोड़ा लेखक Joe Pineda, स्रोत
यह बहुत बुरा है मानक पुस्तकालय में एक और संक्षिप्त अभिव्यक्ति नहीं है। .concat या + = या कुछ
जोड़ा लेखक nmr, स्रोत
@FheheMitha: चूंकि insert के तर्क वैक्टर हैं, इसलिए यह पहले से ही पता है कि कितने तत्व आगे हैं और इसे स्वयं ही संभाल लेंगे। अगर हम सरणी जैसी अन्य चीजें डाल रहे थे, तो पहले अंतरिक्ष को आरक्षित करना उपयोगी था।
जोड़ा लेखक Aidin, स्रोत
@MooingDuck आप सही हैं, मैंने प्रेषक को याद किया और सोचा कि इनपुट इटरेटर संस्करण सभी प्रकार के इटरेटर के लिए लागू होता है। आगे इटरेटर संस्करण बहुत अधिक सामान करता है। इसे इंगित करने के लिए धन्यवाद, मैंने अपनी प्रारंभिक टिप्पणी हटा दी ताकि यह आपके बिना दिखाई न दे।
जोड़ा लेखक Khaur, स्रोत

मैं फ़ंक्शन डालने का उपयोग करूंगा, जैसे कुछ:

vector a, b;
//fill with data
b.insert(b.end(), a.begin(), a.end());
112
जोड़ा

यदि आप सी ++ 11 का उपयोग कर रहे हैं, और केवल उन्हें कॉपी करने के बजाय तत्वों को स्थानांतरित करना चाहते हैं, तो आप std :: move_iterator ( http://en.cppreference.com/w/cpp/iterator/move_iterator ) डालने के साथ (या प्रतिलिपि):

#include 
#include 
#include 

int main(int argc, char** argv) {
  std::vector dest{1,2,3,4,5};
  std::vector src{6,7,8,9,10};

 //Move elements from src to dest.
 //src is left in undefined but safe-to-destruct state.
  dest.insert(
      dest.end(),
      std::make_move_iterator(src.begin()),
      std::make_move_iterator(src.end())
    );

 //Print out concatenated vector.
  std::copy(
      dest.begin(),
      dest.end(),
      std::ostream_iterator(std::cout, "\n")
    );

  return 0;
}

यह इन्स के साथ उदाहरण के लिए अधिक कुशल नहीं होगा, क्योंकि उन्हें स्थानांतरित करने से उन्हें अधिक कुशल नहीं है, लेकिन अनुकूलित चाल के साथ डेटा संरचना के लिए, यह अनावश्यक स्थिति की प्रतिलिपि बनाने से बच सकता है:

#include 
#include 
#include 

int main(int argc, char** argv) {
  std::vector> dest{{1,2,3,4,5}, {3,4}};
  std::vector> src{{6,7,8,9,10}};

 //Move elements from src to dest.
 //src is left in undefined but safe-to-destruct state.
  dest.insert(
      dest.end(),
      std::make_move_iterator(src.begin()),
      std::make_move_iterator(src.end())
    );

  return 0;
}

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

112
जोड़ा
Std :: make_move_iterator() विधि ने std :: unique_ptr के std :: vectors को संयोजित करने का प्रयास करते समय मेरी सहायता की।
जोड़ा लेखक Knitschi, स्रोत

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

std::copy(source.begin(), source.end(), std::back_inserter(destination));

यह पैटर्न उपयोगी है यदि दो वैक्टरों में बिल्कुल वही प्रकार की चीज़ नहीं है, क्योंकि आप एक प्रकार से दूसरे में परिवर्तित करने के लिए std :: back_inserter के बजाय कुछ उपयोग कर सकते हैं।

70
जोड़ा
@ योगेश: दिया गया है, लेकिन आपको पहले reserve को कॉल करने से रोक नहीं है। कारण std :: copy कभी-कभी उपयोगी होता है यदि आप back_inserter के अलावा कुछ और उपयोग करना चाहते हैं।
जोड़ा लेखक Roger Lipscombe, स्रोत
जब आप "एकाधिक आवंटन" कहते हैं, तो यह सत्य है - लेकिन आवंटन की संख्या सबसे खराब लॉग (प्रविष्टियों की संख्या में जोड़ा गया है) - जिसका अर्थ है कि प्रविष्टि जोड़ने की लागत अतिरिक्त प्रविष्टियों की संख्या में स्थिर है। (असल में, इसके बारे में चिंता न करें जब तक प्रोफाइलिंग शो आपको आरक्षित की आवश्यकता न हो)।
जोड़ा लेखक Martin Bonner, स्रोत
आप इसके बजाय ऐसा करने के लिए std :: ट्रांसफॉर्म का उपयोग करना चाह सकते हैं।
जोड़ा लेखक Martin Broadhurst, स्रोत
प्रतिलिपि विधि एक अच्छा तरीका नहीं है। यह push_back एकाधिक समय को कॉल करेगा जिसका अर्थ है कि यदि बहुत से तत्वों को सम्मिलित करना है तो इसका अर्थ कई पुनर्विक्रय हो सकता है। डालने का उपयोग करना बेहतर है क्योंकि वेक्टर कार्यान्वयन पुनर्वितरण से बचने के लिए कुछ अनुकूलन कर सकता है। यह प्रतिलिपि शुरू करने से पहले स्मृति आरक्षित कर सकता है
जोड़ा लेखक Yogesh Arora, स्रोत
std::vector first;
std::vector second;

first.insert(first.end(), second.begin(), second.end());
30
जोड़ा

सी ++ 11 के साथ, मैं वेक्टर बी को जोड़ने के लिए निम्न पसंद करना चाहूंगा:

std::move(b.begin(), b.end(), std::back_inserter(a));

जब a और b ओवरलैप नहीं होते हैं, और b अब और उपयोग नहीं किया जा रहा है।

27
जोड़ा
@ मार्टिनबोनर इसका जिक्र करने के लिए धन्यवाद। शायद मुझे पुराने insert तरीके से वापस जाना चाहिए जो सुरक्षित है।
जोड़ा लेखक Deqing, स्रोत
बस निम्नलिखित हेडर लाइन शुरू करें: # शामिल
जोड़ा लेखक Manohar Reddy Poreddy, स्रोत
अनिश्चित व्यवहार यदि वास्तव में बी है (जो ठीक है अगर आप जानते हैं कि कभी नहीं हो सकता है - लेकिन सामान्य उद्देश्य कोड में जागरूक होने के लायक)।
जोड़ा लेखक Martin Bonner, स्रोत
आह, अन्य std :: चाल। पहली बार आप इसे देखकर भ्रमित कर रहे हैं।
जोड़ा लेखक xaxxon, स्रोत

मैं पहले से ही उल्लेख किया है कि एक पसंद है:

a.insert(a.end(), b.begin(), b.end());

लेकिन यदि आप सी ++ 11 का उपयोग करते हैं, तो एक और सामान्य तरीका है:

a.insert(std::end(a), std::begin(b), std::end(b));

इसके अलावा, किसी प्रश्न का हिस्सा नहीं है, लेकिन यह सलाह दी जाती है कि reserve </कोड> बेहतर प्रदर्शन के लिए जोड़ने से पहले। और यदि आप अपने साथ वेक्टर को संयोजित कर रहे हैं, तो इसे सुरक्षित रखने में विफल रहता है, इसलिए आपको हमेशा reserve होना चाहिए।


तो मूल रूप से आपको क्या चाहिए:

template 
void Append(std::vector& a, const std::vector& b)
{
    a.reserve(a.size() + b.size());
    a.insert(a.end(), b.begin(), b.end());
}
18
जोड़ा
@Asu एडीएल केवल std :: जोड़ देगा यदि a std से आता है, जो सामान्य पहलू को हरा देता है।
जोड़ा लेखक Potatoswatter, स्रोत
std :: तर्क-निर्भर लुकअपअंत (ए) पर्याप्त होगा।
जोड़ा लेखक Asu, स्रोत
अच्छी बात। इस मामले में यह एक वेक्टर है इसलिए यह वैसे भी काम करेगा, लेकिन हाँ यह एक बेहतर समाधान है।
जोड़ा लेखक Asu, स्रोत

आपको वेक्टर :: सम्मिलित का उपयोग करना चाहिए

v1.insert(v1.end(), v2.begin(), v2.end());
5
जोड़ा

यदि आप मजबूत अपवाद गारंटी में रुचि रखते हैं (जब कॉपी कन्स्ट्रक्टर अपवाद फेंक सकता है):

template
inline void append_copy(std::vector& v1, const std::vector& v2)
{
    const auto orig_v1_size = v1.size();
    v1.reserve(orig_v1_size + v2.size());
    try
    {
        v1.insert(v1.end(), v2.begin(), v2.end());
    }
    catch(...)
    {
        v1.erase(v1.begin() + orig_v1_size, v1.end());
        throw;
    }
}

मजबूत गारंटी के साथ समान append_move सामान्य रूप से लागू नहीं किया जा सकता है यदि वेक्टर तत्व के चालक निर्माता फेंक सकते हैं (जो कि असंभव है लेकिन अभी भी)।

4
जोड़ा
सम्मिलित करें पहले से ही इसे संभालता है। साथ ही, मिटाएं पर यह कॉल आकार बदलें के बराबर है।
जोड़ा लेखक Potatoswatter, स्रोत
v1.erase (... के लिए भी फेंकना संभव नहीं है?
जोड़ा लेखक camelCase, स्रोत
vector v1 = {1, 2, 3, 4, 5};
vector v2 = {11, 12, 13, 14, 15};
copy(v2.begin(), v2.end(), back_inserter(v1));
3
जोड़ा
हालांकि यह कोड स्निपेट समस्या का समाधान कर सकता है, यह स्पष्ट नहीं करता है कि यह सवाल का जवाब क्यों देता है या कैसे। कृपया अपने कोड के लिए स्पष्टीकरण शामिल करें , क्योंकि यह वास्तव में आपकी पोस्ट की गुणवत्ता में सुधार करने में मदद करता है। फ़्लैगर्स/समीक्षकों: कोड-केवल उत्तर जैसे कि इस के लिए, डाउनवोट, हटाएं नहीं! </ए> (नोट: यह उत्तर वास्तव में स्पष्टीकरण देने के लिए काफी आसान हो सकता है, और इस प्रकार डाउनवोट्स, अनावश्यक। आप अभी भी एनएए/वीएलक्यू झंडे को रोकने के लिए एक स्पष्टीक
जोड़ा लेखक Scott Weldon, स्रोत

इसे अपनी हेडर फ़ाइल में जोड़ें:

template  vector concat(vector &a, vector &b) {
    vector ret = vector();
    copy(a.begin(), a.end(), back_inserter(ret));
    copy(b.begin(), b.end(), back_inserter(ret));
    return ret;
}

और इस तरह इसका इस्तेमाल करें:

vector a = vector();
vector b = vector();

a.push_back(1);
a.push_back(2);
b.push_back(62);

vector r = concat(a, b);

आर में [1,2,62]

2
जोड़ा
पता नहीं क्यों यह नीचे मतदान किया गया था। यह ऐसा करने का सबसे प्रभावी तरीका नहीं हो सकता है लेकिन यह गलत नहीं है और प्रभावी है।
जोड़ा लेखक leeor_net, स्रोत

श्रेणी v3 के साथ, आपके पास आलसी concatenation हो सकता है:

ranges::view::concat(v1, v2)

Demo.

2
जोड़ा

यहां C ++ 11 चाल semantics का उपयोग कर एक सामान्य उद्देश्य समाधान है:

template 
std::vector concat(const std::vector& lhs, const std::vector& rhs)
{
    if (lhs.empty()) return rhs;
    if (rhs.empty()) return lhs;
    std::vector result {};
    result.reserve(lhs.size() + rhs.size());
    result.insert(result.cend(), lhs.cbegin(), lhs.cend());
    result.insert(result.cend(), rhs.cbegin(), rhs.cend());
    return result;
}

template 
std::vector concat(std::vector&& lhs, const std::vector& rhs)
{
    lhs.insert(lhs.cend(), rhs.cbegin(), rhs.cend());
    return std::move(lhs);
}

template 
std::vector concat(const std::vector& lhs, std::vector&& rhs)
{
    rhs.insert(rhs.cbegin(), lhs.cbegin(), lhs.cend());
    return std::move(rhs);
}

template 
std::vector concat(std::vector&& lhs, std::vector&& rhs)
{
    if (lhs.empty()) return std::move(rhs);
    lhs.insert(lhs.cend(), std::make_move_iterator(rhs.begin()), std::make_move_iterator(rhs.end()));
    return std::move(lhs);
}

ध्यान दें कि यह वेक्टर में संलग्न करें से अलग है।

1
जोड़ा

यदि आप जो खोज रहे हैं वह सृजन के बाद किसी दूसरे को वेक्टर जोड़ने का एक तरीका है, vector :: insert आपकी सबसे अच्छी शर्त है, जैसा कि कई बार उत्तर दिया गया है, उदाहरण के लिए:

vector first = {13};
const vector second = {42};

first.insert(first.end(), second.cbegin(), second.cend());

Sadly there's no way to construct a const vector, as above you must construct and then insert.


If what you're actually looking for is a container to hold the concatenation of these two vectors, there may be something better available to you, if:

  1. आपका वेक्टर प्राइमेटिव
  2. शामिल है
  3. आपके निहित प्राइमेटिव आकार 32-बिट या छोटे
  4. हैं
  5. आप एक const कंटेनर
  6. चाहते हैं

यदि उपरोक्त सभी सत्य हैं, तो मैं basic_string char_type कौन सा वेक्टर में निहित आदिम के आकार से मेल खाता है। आपको अपने कोड में एक static_assert शामिल करना चाहिए इन आकारों को मान्य रखें लगातार बने रहें:

static_assert(sizeof(char32_t) == sizeof(int));

इस होल्डिंग के साथ आप बस कर सकते हैं:

const u32string concatenation = u32string(first.cbegin(), first.cend()) + u32string(second.cbegin(), second.cend());

For more information on the differences between string and vector you can look here: https://stackoverflow.com/a/35558008/2642059

For a live example of this code you can look here: http://ideone.com/7Iww3I

0
जोड़ा

ईमानदार होने के लिए, आप दो वैक्टरों से दूसरे वैक्टरों में तत्वों की प्रतिलिपि बनाकर दो वैक्टरों को तेजी से जोड़ सकते हैं या केवल दो वैक्टरों में से एक को जोड़ सकते हैं! यह आपके लक्ष्य पर निर्भर करता है।

Method 1: Assign new vector with its size is the sum of two original vectors' size.

vector concat_vector = vector();
concat_vector.setcapacity(vector_A.size() + vector_B.size());
// Loop for copy elements in two vectors into concat_vector

Method 2: Append vector A by adding/inserting elements of vector B.

// Loop for insert elements of vector_B into vector_A with insert() 
function: vector_A.insert(vector_A .end(), vector_B.cbegin(), vector_B.cend());
0
जोड़ा
आपका उत्तर क्या जोड़ता है जो पहले से ही अन्य उत्तरों में प्रदान नहीं किया गया है?
जोड़ा लेखक Mat, स्रोत
यदि मूल वेक्टर की आवश्यकता नहीं है, तो std :: move_iterator का उपयोग करना बेहतर हो सकता है ताकि प्रतिलिपि के बजाय तत्व स्थानांतरित हो जाएं। ( en.cppreference.com/w/cpp/iterator/move_iterator देखें) ।
जोड़ा लेखक tmlen, स्रोत
@Mat: बोल्ड अक्षर।
जोड़ा लेखक marcv81, स्रोत

Concatenate के लिए एक सामान्य प्रदर्शन वृद्धि वैक्टर के आकार की जांच करना है। और बड़े के साथ छोटे को मर्ज/डालें।

//vector v1,v2;
if(v1.size()>v2.size()){
    v1.insert(v1.end(),v2.begin(),v2.end());
}else{
    v1.insert(v2.end(),v1.begin(),v1.end());
}
0
जोड़ा