Hoe concateneer ik twee std::vector
s?
Antwoord 1, Autoriteit 100%
vector1.insert( vector1.end(), vector2.begin(), vector2.end() );
Antwoord 2, Autoriteit 28%
Als u C++ 11 gebruikt en de elementen wilt verplaatsen in plaats van ze alleen maar te kopiëren, kunt u std::move_iterator
samen met insert (of kopie):
#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;
}
Dit zal niet efficiënter zijn voor het voorbeeld met Ints, omdat het verplaatsen van ze niet efficiënter is dan het kopiëren van ze, maar voor een data-structuur met geoptimaliseerde bewegingen, kan het voorkomen dat het onnodige staat wordt gekopieerd:
#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;
}
Na de verplaatsing blijft het element van src in een ongedefinieerde maar veilige staat om te vernietigen, en zijn eerdere elementen werden aan het einde rechtstreeks overgebracht naar het nieuwe element van dest.
Antwoord 3, autoriteit 20%
Ik zou de insert-functiegebruiken, zoiets als:
vector<int> a, b;
//fill with data
b.insert(b.end(), a.begin(), a.end());
Antwoord 4, autoriteit 10%
Of je zou kunnen gebruiken:
std::copy(source.begin(), source.end(), std::back_inserter(destination));
Dit patroon is handig als de twee vectoren niet precies hetzelfde type ding bevatten, omdat je iets kunt gebruiken in plaats van std::back_inserter om van het ene type naar het andere te converteren.
Antwoord 5, autoriteit 8%
Met C++11 zou ik het volgende prefereren om vector b aan a toe te voegen:
std::move(b.begin(), b.end(), std::back_inserter(a));
wanneer a
en b
elkaar niet overlappen, en b
niet meer wordt gebruikt.
Dit is std::move
van <algorithm>
, niet de gebruikelijkestd::move
van <utility>
.
Antwoord 6, autoriteit 5%
std::vector<int> first;
std::vector<int> second;
first.insert(first.end(), second.begin(), second.end());
Antwoord 7, autoriteit 3%
Ik geef de voorkeur aan een die al genoemd is:
a.insert(a.end(), b.begin(), b.end());
Maar als je C++11 gebruikt, is er nog een algemenere manier:
a.insert(std::end(a), std::begin(b), std::end(b));
Ook geen onderdeel van een vraag, maar het is raadzaam om reserve
voordat u toevoegt voor betere prestaties. En als u vector met zichzelf samenvoegt, mislukt het zonder te reserveren, dus u moet altijd reserve
.
Dus eigenlijk wat je nodig hebt:
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());
}
Antwoord 8, autoriteit 3%
Met range v3heb je misschien een luieaaneenschakeling :
ranges::view::concat(v1, v2)
Demo.
Antwoord 9, autoriteit 2%
Een algemene prestatieverbeteringvoor concatenate is het controleren van de grootte van de vectoren. En voeg de kleinere samen met de grotere.
//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());
}
Antwoord 10, autoriteit 2%
Als u vectoren beknopt wilt kunnen samenvoegen, kunt u de operator +=
overbelasten.
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;
}
Dan kun je het zo noemen:
vector1 += vector2;
Antwoord 11
U moet vector::insert
gebruiken
v1.insert(v1.end(), v2.begin(), v2.end());
Antwoord 12
Als u geïnteresseerd bent in een sterke uitzonderingsgarantie (wanneer de copy-constructor een uitzondering kan genereren):
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;
}
}
Vergelijkbare append_move
met sterke garantie kan in het algemeen niet worden geïmplementeerd als de move-constructor van het vectorelement kan gooien (wat onwaarschijnlijk is, maar toch).
Antwoord 13
Er is een algoritme std::merge
van C++17, wat heel gemakkelijk te gebruiken is wanneer de invoervectoren zijn gesorteerd,
Hieronder staat het voorbeeld:
#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;
}
Antwoord 14
Voeg deze toe aan je headerbestand:
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;
}
en gebruik het op deze manier:
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 zal [1,2,62] bevatten
Antwoord 15
Als het uw doel eenvoudigweg is om het bereik van waarden te herhalen voor alleen-lezen doeleinden, is een alternatief om beide vectoren rond een proxy (O(1)) te wikkelen in plaats van ze te kopiëren (O(n)), zodat ze worden onmiddellijk als een enkele, aaneengesloten beschouwd.
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
Raadpleeg https://stackoverflow.com/a/55838758/2379625voor meer details, waaronder de ‘VecProxy ‘ implementatie evenals pro’s & nadelen.
Antwoord 16
Hier is een algemene oplossing met C++11 move-semantiek:
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);
}
Merk op hoe dit verschilt van append
ing aan een vector
.
Antwoord 17
vector<int> v1 = {1, 2, 3, 4, 5};
vector<int> v2 = {11, 12, 13, 14, 15};
copy(v2.begin(), v2.end(), back_inserter(v1));
Antwoord 18
U kunt uw eigen sjabloon voorbereiden voor + operator:
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;
}
Volgende – gebruik gewoon +:
vector<int> a{1, 2, 3, 4};
vector<int> b{5, 6, 7, 8};
for (auto x: a + b)
cout << x << " ";
cout << endl;
Dit voorbeeld geeft uitvoer:
1 2 3 4 5 6 7 8
Antwoord 19
Ik heb deze functie geïmplementeerd die een willekeurig aantal containers samenvoegt, van rvalue-referenties afwijkt en anders kopieert
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;
}
Antwoord 20
Deze oplossing kan een beetje ingewikkeld zijn, maar boost-range
heeft ook enkele andere leuke dingen te bieden.
#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;
}
Vaak is het de bedoeling om vector a
en b
te combineren door er gewoon een bewerking over te doen. In dit geval is er de belachelijk eenvoudige join
-functie.
#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;
}
Voor grote vectoren kan dit een voordeel zijn, omdat er niet wordt gekopieerd. Het kan ook worden gebruikt voor het gemakkelijk kopiëren van een generalisatie naar meer dan één container.
Om de een of andere reden gaat er niets boven boost::join(a,b,c)
, wat redelijk zou kunnen zijn.
Antwoord 21
Voor containers die push_back
bieden (string, vector, deque, …):
std::copy(std::begin(input), std::end(input), std::back_inserter(output))
en
voor containers die insert
bieden (kaarten, sets):
std::copy(std::begin(input), std::end(input), std::inserter(output, output.end()))
Antwoord 22
Als u op zoek bent naar een manier om een vector aan een andere toe te voegen na het maken, vector::insert
is de beste keuze, zoals al meerdere keren is beantwoord, bijvoorbeeld:
vector<int> first = {13};
const vector<int> second = {42};
first.insert(first.end(), second.cbegin(), second.cend());
Helaas is er geen manier om een const vector<int>
te construeren, zoals hierboven moet je construeren en vervolgens insert
.
Als u eigenlijk op zoek bent naar een container voor de aaneenschakeling van deze twee vector<int>
en, is er misschien iets beters voor u beschikbaar, als:
- Uw
vector
bevat primitieven - Uw ingesloten primitieven zijn 32-bits of kleiner
- U wilt een
const
container
Als het bovenstaande allemaal waar is, raad ik aan om de basic_string
die char_type
is, komt overeen met de grootte van de primitief in je vector
. U moet een static_assert
in uw code opnemen om valideer deze maten consistent blijven:
static_assert(sizeof(char32_t) == sizeof(int));
Met deze instelling waar kun je gewoon het volgende doen:
const u32string concatenation = u32string(first.cbegin(), first.cend()) + u32string(second.cbegin(), second.cend());
Voor meer informatie over de verschillen tussen string
en vector
kun je hier kijken: https://stackoverflow.com/a/35558008/2642059
Voor een live voorbeeld van deze code kun je hier kijken: http://ideone.com/7Iww3I
Antwoord 23
U kunt dit doen met vooraf geïmplementeerde STL-algoritmen met behulp van een sjabloon voor gebruik van een polymorf type.
#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;
}
U kunt de tweede vector wissen als u deze niet verder wilt gebruiken (clear()
-methode).
Antwoord 24
Samenvoeg twee std::vector-s
met for
lussen in één 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(int i = 0; i < v1.size(); i++) //for loop 1
{
suma.push_back(v1[i]);
}
for(int i = 0; i< v2.size(); i++) //for loop 2
{
suma.push_back(v2[i]);
}
for(int i = 0; i < suma.size(); i++) //for loop 3-output
{
std::cout << suma[i];
}
Antwoord 25
Probeer, maak twee vectoren en voeg tweede vector toe aan de eerste vector,
Code:
std::vector<int> v1{1,2,3};
std::vector<int> v2{4,5};
for(int i = 0; i<v2.size();i++)
{
v1.push_back(v2[i]);
}
V1: 1,2,3.
Beschrijving:
Terwijl ik geen V2-formaat, duw het element, index I in V1-vector.
Antwoord 26
Om eerlijk te zijn, kunt u twee vectoren snel aansluiten door elementen van twee vectoren naar de andere te kopiëren of alleen een van de twee vectoren toe te voegen!. Het hangt af van uw doel.
Methode 1: Nieuwe vector toewijzen met de grootte is de som van de grootte van twee originele vectoren.
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
Methode 2: Bevestig Vector A door elementen van vector B toe te voegen / in te voegen.
// 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());