मैं दो std::vector
एस कैसे सम्मिलित करूं ?
a + b
या a.concat(b)
मानक पुस्तकालय में? हो सकता है कि डिफ़ॉल्ट क्रियान्वयन सब-
मैं दो std::vector
एस कैसे सम्मिलित करूं ?
a + b
या a.concat(b)
मानक पुस्तकालय में? हो सकता है कि डिफ़ॉल्ट क्रियान्वयन सब-
जवाबों:
vector1.insert( vector1.end(), vector2.begin(), vector2.end() );
reserve
पहले गंतव्य वेक्टर पर कॉल करना मददगार है ?
vector1.capacity() >= 2 * vector1.size()
। जब तक आपने फोन नहीं किया, तब तक यह असामान्य है std::vector::reserve()
। अन्यथा वेक्टर फिर से जुड़ जाएगा, 2 और 3 के रूप में पारित किए गए पुनरावृत्तियों को अमान्य करना
.concat
या +=
कुछ और
यदि आप C ++ 11 का उपयोग कर रहे हैं, और तत्वों को केवल कॉपी करने के बजाय स्थानांतरित करना चाहते हैं, तो आप std::move_iterator
सम्मिलित (या प्रतिलिपि) के साथ उपयोग कर सकते हैं :
#include <vector>
#include <iostream>
#include <iterator>
int main(int argc, char** argv) {
std::vector<int> dest{1,2,3,4,5};
std::vector<int> 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<int>(std::cout, "\n")
);
return 0;
}
यह चींटियों के साथ उदाहरण के लिए अधिक कुशल नहीं होगा, क्योंकि उन्हें स्थानांतरित करना उनकी नकल करने की तुलना में अधिक कुशल नहीं है, लेकिन अनुकूलित चाल के साथ डेटा संरचना के लिए, यह अनावश्यक स्थिति की नकल करने से बच सकता है:
#include <vector>
#include <iostream>
#include <iterator>
int main(int argc, char** argv) {
std::vector<std::vector<int>> dest{{1,2,3,4,5}, {3,4}};
std::vector<std::vector<int>> 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 के तत्व को अपरिभाषित लेकिन सुरक्षित-से-विनाश वाली स्थिति में छोड़ दिया गया है, और इसके पूर्व तत्वों को अंत में नए तत्व को नष्ट करने के लिए सीधे स्थानांतरित कर दिया गया था।
std::move(src.begin(), src.end(), back_inserter(dest))
?
मैं सम्मिलित फ़ंक्शन का उपयोग करूंगा , जैसे कुछ:
vector<int> a, b;
//fill with data
b.insert(b.end(), a.begin(), a.end());
या आप उपयोग कर सकते हैं:
std::copy(source.begin(), source.end(), std::back_inserter(destination));
यह पैटर्न उपयोगी है यदि दो वैक्टर में एक ही प्रकार की चीज नहीं है, क्योंकि आप एक प्रकार से दूसरे प्रकार में बदलने के लिए std :: back_inserter के बजाय कुछ का उपयोग कर सकते हैं।
reserve
पहले कॉल करना बंद कर दे । कारण std::copy
कभी-कभी उपयोगी होता है यदि आप इसके अलावा कुछ और उपयोग करना चाहते हैं back_inserter
।
C ++ 11 के साथ, मैं वेक्टर बी को एक में जोड़ना चाहूंगा:
std::move(b.begin(), b.end(), std::back_inserter(a));
जब a
और b
ओवरलैप नहीं किया जाता है, और b
अब और इस्तेमाल किया जा करने के लिए नहीं जा रहा है।
यह वह जगह है std::move
से <algorithm>
, नहीं हमेशा की तरह std::move
से <utility>
।
insert
तरीके से वापस मुड़ जाना चाहिए जो सुरक्षित है।
insert()
साथ move_iterator
रों? यदि हां, तो कैसे?
std::move
हम यहां क्या बात कर रहे हैं, क्योंकि ज्यादातर लोग इस अधिभार को नहीं जानते हैं। आशा है कि यह एक सुधार है।
std::vector<int> first;
std::vector<int> second;
first.insert(first.end(), second.begin(), second.end());
मैं पहले से उल्लेखित एक को पसंद करता हूं:
a.insert(a.end(), b.begin(), b.end());
लेकिन अगर आप C ++ 11 का उपयोग करते हैं, तो एक और सामान्य तरीका है:
a.insert(std::end(a), std::begin(b), std::end(b));
इसके अलावा, एक सवाल का हिस्सा नहीं है, लेकिन reserve
बेहतर प्रदर्शन के लिए आवेदन करने से पहले उपयोग करना उचित है । और यदि आप वेक्टर को स्वयं के साथ समेट रहे हैं, तो इसे जलाए बिना यह विफल हो जाता है, इसलिए आपको हमेशा ऐसा करना चाहिए reserve
।
तो मूल रूप से आपको क्या चाहिए:
template <typename T>
void Append(std::vector<T>& a, const std::vector<T>& b)
{
a.reserve(a.size() + b.size());
a.insert(a.end(), b.begin(), b.end());
}
std::
यदि प्रकार से a
आता है std
, जो सामान्य पहलू को हरा देता है।
आपको वेक्टर :: इंसर्ट का उपयोग करना चाहिए
v1.insert(v1.end(), v2.begin(), v2.end());
कॉकटेल के आकार को जांचने के लिए एक सामान्य प्रदर्शन को बढ़ावा देना है। और बड़े वाले के साथ छोटे को मर्ज / इन्सर्ट करें।
//vector<int> v1,v2;
if(v1.size()>v2.size()) {
v1.insert(v1.end(),v2.begin(),v2.end());
} else {
v2.insert(v2.end(),v1.begin(),v1.end());
}
v1.insert(v2.end()...
एक पुनरावृत्ति का उपयोग कर रहा v2
है v1
।
यदि आप कंसीव करने वाले वैक्टर्स को कंफर्टेबल करना चाहते हैं, तो आप +=
ऑपरेटर को ओवरलोड कर सकते हैं ।
template <typename T>
std::vector<T>& operator +=(std::vector<T>& vector1, const std::vector<T>& vector2) {
vector1.insert(vector1.end(), vector2.begin(), vector2.end());
return vector1;
}
तो आप इसे इस तरह से कॉल कर सकते हैं:
vector1 += vector2;
यदि आप मजबूत अपवाद गारंटी में रुचि रखते हैं (जब कॉपी कंस्ट्रक्टर अपवाद फेंक सकता है):
template<typename T>
inline void append_copy(std::vector<T>& v1, const std::vector<T>& 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
अगर सदिश तत्व की चाल निर्माणकर्ता फेंक सकता है (जो कि अभी भी संभावना नहीं है) लेकिन मजबूत गारंटी के साथ समान रूप से लागू नहीं किया जा सकता है।
v1.erase(...
फेंकना भी संभव नहीं है ?
insert
पहले से ही यह संभालती है। इसके अलावा, यह कॉल erase
एक के बराबर है resize
।
इसे अपनी हेडर फ़ाइल में जोड़ें:
template <typename T> vector<T> concat(vector<T> &a, vector<T> &b) {
vector<T> ret = vector<T>();
copy(a.begin(), a.end(), back_inserter(ret));
copy(b.begin(), b.end(), back_inserter(ret));
return ret;
}
और इसे इस तरह से उपयोग करें:
vector<int> a = vector<int>();
vector<int> b = vector<int>();
a.push_back(1);
a.push_back(2);
b.push_back(62);
vector<int> r = concat(a, b);
r में [1,2,62] शामिल होंगे
यहाँ C ++ 11 चाल शब्दार्थ का उपयोग कर एक सामान्य उद्देश्य समाधान है:
template <typename T>
std::vector<T> concat(const std::vector<T>& lhs, const std::vector<T>& rhs)
{
if (lhs.empty()) return rhs;
if (rhs.empty()) return lhs;
std::vector<T> 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 <typename T>
std::vector<T> concat(std::vector<T>&& lhs, const std::vector<T>& rhs)
{
lhs.insert(lhs.cend(), rhs.cbegin(), rhs.cend());
return std::move(lhs);
}
template <typename T>
std::vector<T> concat(const std::vector<T>& lhs, std::vector<T>&& rhs)
{
rhs.insert(rhs.cbegin(), lhs.cbegin(), lhs.cend());
return std::move(rhs);
}
template <typename T>
std::vector<T> concat(std::vector<T>&& lhs, std::vector<T>&& 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);
}
ध्यान दें कि यह append
आईएनजी से अलग कैसे है vector
।
आप अपना स्वयं का टेम्पलेट + ऑपरेटर के लिए तैयार कर सकते हैं:
template <typename T>
inline T operator+(const T & a, const T & b)
{
T res = a;
res.insert(res.end(), b.begin(), b.end());
return res;
}
अगली बात - बस उपयोग +:
vector<int> a{1, 2, 3, 4};
vector<int> b{5, 6, 7, 8};
for (auto x: a + b)
cout << x << " ";
cout << endl;
यह उदाहरण आउटपुट देता है:
1 2 3 4 5 6 7 8
T operator+(const T & a, const T & b)
खतरनाक है, इसका उपयोग करना बेहतर है vector<T> operator+(const vector<T> & a, const vector<T> & b)
।
C ++ 17std::merge
से एक एल्गोरिथ्म है , जिसका उपयोग करना बहुत आसान है,
नीचे उदाहरण है:
#include <iostream>
#include <vector>
#include <algorithm>
int main()
{
//DATA
std::vector<int> v1{2,4,6,8};
std::vector<int> v2{12,14,16,18};
//MERGE
std::vector<int> dst;
std::merge(v1.begin(), v1.end(), v2.begin(), v2.end(), std::back_inserter(dst));
//PRINT
for(auto item:dst)
std::cout<<item<<" ";
return 0;
}
std::vector::insert
, लेकिन यह कुछ अलग करता है: दो श्रेणियों को एक नई श्रेणी में विलय करना बनाम एक दूसरे के अंत में एक वेक्टर सम्मिलित करना। उत्तर में उल्लेख के लायक?
यदि आपका लक्ष्य केवल रीड-ओनली उद्देश्यों के लिए मानों की सीमा पर पुनरावृति करना है, तो एक विकल्प दोनों वैक्टर को प्रॉक्सी (O (1)) के चारों ओर लपेटने के बजाय उन्हें (O (n)) कॉपी करने के लिए है, इसलिए उन्हें तुरंत देखा जाता है एक एकल के रूप में, एक सन्निहित।
std::vector<int> A{ 1, 2, 3, 4, 5};
std::vector<int> B{ 10, 20, 30 };
VecProxy<int> AB(A, B); // ----> O(1)!
for (size_t i = 0; i < AB.size(); i++)
std::cout << AB[i] << " "; // ----> 1 2 3 4 5 10 20 30
अधिक जानकारी के लिए https://stackoverflow.com/a/55838758/2379625 देखें, जिसमें 'VecProxy' कार्यान्वयन के साथ-साथ पेशेवरों और विपक्ष भी शामिल हैं।
vector<int> v1 = {1, 2, 3, 4, 5};
vector<int> v2 = {11, 12, 13, 14, 15};
copy(v2.begin(), v2.end(), back_inserter(v1));
मैंने इस फ़ंक्शन को कार्यान्वित किया है जो किसी भी संख्या में कंटेनरों को समेटता है, प्रतिद्वंद्वियों-संदर्भों से आगे बढ़ता है और अन्यथा कॉपी करता है
namespace internal {
// Implementation detail of Concatenate, appends to a pre-reserved vector, copying or moving if
// appropriate
template<typename Target, typename Head, typename... Tail>
void AppendNoReserve(Target* target, Head&& head, Tail&&... tail) {
// Currently, require each homogenous inputs. If there is demand, we could probably implement a
// version that outputs a vector whose value_type is the common_type of all the containers
// passed to it, and call it ConvertingConcatenate.
static_assert(
std::is_same_v<
typename std::decay_t<Target>::value_type,
typename std::decay_t<Head>::value_type>,
"Concatenate requires each container passed to it to have the same value_type");
if constexpr (std::is_lvalue_reference_v<Head>) {
std::copy(head.begin(), head.end(), std::back_inserter(*target));
} else {
std::move(head.begin(), head.end(), std::back_inserter(*target));
}
if constexpr (sizeof...(Tail) > 0) {
AppendNoReserve(target, std::forward<Tail>(tail)...);
}
}
template<typename Head, typename... Tail>
size_t TotalSize(const Head& head, const Tail&... tail) {
if constexpr (sizeof...(Tail) > 0) {
return head.size() + TotalSize(tail...);
} else {
return head.size();
}
}
} // namespace internal
/// Concatenate the provided containers into a single vector. Moves from rvalue references, copies
/// otherwise.
template<typename Head, typename... Tail>
auto Concatenate(Head&& head, Tail&&... tail) {
size_t totalSize = internal::TotalSize(head, tail...);
std::vector<typename std::decay_t<Head>::value_type> result;
result.reserve(totalSize);
internal::AppendNoReserve(&result, std::forward<Head>(head), std::forward<Tail>(tail)...);
return result;
}
यदि आप जिस चीज़ की तलाश कर रहे हैं, वह एक वेक्टर को निर्माण के बाद दूसरे में जोड़ने का एक तरीका है, vector::insert
तो आपका सबसे अच्छा दांव है, जैसा कि कई बार उत्तर दिया गया है, उदाहरण के लिए:
vector<int> first = {13};
const vector<int> second = {42};
first.insert(first.end(), second.cbegin(), second.cend());
अफसोस की बात है कि निर्माण का कोई तरीका नहीं है const vector<int>
, जैसा कि ऊपर आपको निर्माण करना चाहिए और फिर insert
।
यदि आप वास्तव में जिस चीज की तलाश कर रहे हैं, वह इन दो vector<int>
एस के संयोजन को रखने के लिए एक कंटेनर है , तो आपके लिए कुछ बेहतर उपलब्ध हो सकता है, यदि:
vector
आदिम हैंconst
कंटेनर चाहिएयदि उपरोक्त सभी सत्य हैं, तो मैं सुझाव दूंगा कि आपके मैच में basic_string
कौन char_type
आदिम के आकार का उपयोग करता है vector
। static_assert
इन आकारों के अनुरूप रहने के लिए आपको अपने कोड में एक को शामिल करना चाहिए :
static_assert(sizeof(char32_t) == sizeof(int));
इस सच को पकड़ कर आप बस कर सकते हैं:
const u32string concatenation = u32string(first.cbegin(), first.cend()) + u32string(second.cbegin(), second.cend());
string
और vector
आप के बीच के अंतर के बारे में अधिक जानकारी के लिए यहाँ देख सकते हैं: https://stackoverflow.com/a/35558008/2642059
इस कोड के जीवंत उदाहरण के लिए आप यहां देख सकते हैं: http://ideone.com/7Iww3I
यह समाधान थोड़ा जटिल हो सकता है, लेकिन boost-range
इसमें कुछ अन्य अच्छी चीजें भी हैं।
#include <iostream>
#include <vector>
#include <boost/range/algorithm/copy.hpp>
int main(int, char**) {
std::vector<int> a = { 1,2,3 };
std::vector<int> b = { 4,5,6 };
boost::copy(b, std::back_inserter(a));
for (auto& iter : a) {
std::cout << iter << " ";
}
return EXIT_SUCCESS;
}
अक्सर लोगों का इरादा वेक्टर को संयोजित करना होता है a
और b
बस कुछ ऑपरेशन करने से अधिक पुनरावृति होती है। इस मामले में, हास्यास्पद सरल join
कार्य है।
#include <iostream>
#include <vector>
#include <boost/range/join.hpp>
#include <boost/range/algorithm/copy.hpp>
int main(int, char**) {
std::vector<int> a = { 1,2,3 };
std::vector<int> b = { 4,5,6 };
std::vector<int> c = { 7,8,9 };
// Just creates an iterator
for (auto& iter : boost::join(a, boost::join(b, c))) {
std::cout << iter << " ";
}
std::cout << "\n";
// Can also be used to create a copy
std::vector<int> d;
boost::copy(boost::join(a, boost::join(b, c)), std::back_inserter(d));
for (auto& iter : d) {
std::cout << iter << " ";
}
return EXIT_SUCCESS;
}
बड़े वैक्टर के लिए यह एक फायदा हो सकता है, क्योंकि कोई नकल नहीं है। इसका उपयोग एक सामान्य से अधिक कंटेनर में आसानी से कॉपी करने के लिए भी किया जा सकता है।
किसी कारण से ऐसा कुछ नहीं है boost::join(a,b,c)
, जो उचित हो सकता है।
आप इसे पॉलीमॉर्फिक प्रकार के उपयोग के लिए टेम्पलेट का उपयोग करके पूर्व-लागू एसटीएल एल्गोरिदम के साथ कर सकते हैं।
#include <iostream>
#include <vector>
#include <algorithm>
template<typename T>
void concat(std::vector<T>& valuesa, std::vector<T>& valuesb){
for_each(valuesb.begin(), valuesb.end(), [&](int value){ valuesa.push_back(value);});
}
int main()
{
std::vector<int> values_p={1,2,3,4,5};
std::vector<int> values_s={6,7};
concat(values_p, values_s);
for(auto& it : values_p){
std::cout<<it<<std::endl;
}
return 0;
}
यदि आप इसे आगे ( clear()
विधि) उपयोग नहीं करना चाहते हैं तो आप दूसरे वेक्टर को साफ़ कर सकते हैं ।
एक में लूप के std::vector-s
साथ दो समेटें ।for
std::vector
उदाहरण:
std::vector <int> v1 {1, 2, 3};//declare vector1
std::vector <int> v2 {4, 5};//declare vector2
std::vector <int> suma;//declare vector suma
for(auto i = 0; i < v1.size()-1;i++)//for loop 1
{
suma.push_back(v1[i]);
}
for(auto i = 0; i< v2.size()-1;i++)/for loop 2
{
suma.push_back(v2[i]);
}
for(auto i = 0; i < suma.size(); i++)//for loop 3-output
{
std::cout<<suma[i];
}
इस कोड को लिखें main()
।
for
लूप गलत हैं। एक वेक्टर में मान्य अनुक्रमित 0 से होते हैं size()-1
। आप लूप समाप्ति शर्तों i < v1.size()
का उपयोग करना चाहिए , <
नहीं का उपयोग कर <=
। गलत स्थिति का उपयोग करके कंटेनर के बाहर मेमोरी एक्सेस की जाती है।
auto
मैनुअल इंडेक्सिंग के बजाय पुनरावृत्तियों का उपयोग करना चाहिए । आप इस बात की परवाह नहीं करते हैं कि आप किस इंडेक्स को केवल इतना समझ रहे हैं कि यह क्रमिक रूप से किया जाता है।
size()-1
अपनी दो लूप स्थितियों में उपयोग क्यों कर रहे हैं? यह पिछले वेक्टर तत्वों को छोड़ देता है। तीसरा लूप अब केवल एक ही सही है।
ईमानदार होने के लिए, आप दो वैक्टर से तत्वों को दूसरे वैक्टर में कॉपी करके तेजी से दो वैक्टर को हटा सकते हैं या केवल दो वैक्टर में से एक को जोड़ सकते हैं। यह आपके उद्देश्य पर निर्भर करता है।
विधि 1: नए वेक्टर को उसके आकार के साथ असाइन करें दो मूल वैक्टर के आकार का योग है।
vector<int> concat_vector = vector<int>();
concat_vector.setcapacity(vector_A.size() + vector_B.size());
// Loop for copy elements in two vectors into concat_vector
विधि 2: वेक्टर B के तत्वों को जोड़ / जोड़कर वेक्टर A को जोड़िए।
// 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());
std::move_iterator
ताकि कॉपी किए गए तत्वों को स्थानांतरित किया जा सके। (देखें en.cppreference.com/w/cpp/iterator/move_iterator )।
setcapacity
? क्या है function:
?
resize
विधि के बारे में बात कर रहा है ।