I have a vector of vectors and I want to take the contents of it into a single column vector. i.e.,
input: A = [[1 2] [3 4]]
output: v = [[1][2][3][4]] (column vector)
Is there a quick way of doing this in C++?
I have a vector of vectors and I want to take the contents of it into a single column vector. i.e.,
input: A = [[1 2] [3 4]]
output: v = [[1][2][3][4]] (column vector)
Is there a quick way of doing this in C++?
Like this:
std::vector<std::vector<int>> a = {{1, 2}, {3, 4}};
std::vector<std::vector<int>> b;
for ( auto& row : a )
{
for ( auto item: row )
{
b.push_back(std::vector<int>{item});
}
}
You could std::copy
every row using std::back_inserter
like so:
int main()
{
std::vector<std::vector<int>> v = {{1, 2, 3}, {2, 2, 3}};
std::vector<int> b;
for(auto& vec : v){
std::copy(vec.begin(), vec.end(), std::back_inserter(b));
}
}
If you want to copy all the elements from a vector of vectors into a single vector then utilize the two loops:
std::vector<std::vector<int>> vv = { { 1, 2, 3 },
{ 4, 5, 6 },
{ 7, 8, 9 } };
std::vector<int> v;
for (auto row : vv) {
for (auto el : row) {
v.push_back(el);
}
}
//print out the vector:
for (auto el : v) {
std::cout << el << ' ';
}
or utilize the std::copy function.
Unfortunately I have to tell you, that every other answer, at least until now, is not as good as it seems.
Let us step through the answers; in the end I tell you how to handle it properly.
std::vector<std::vector<int>> v = {{1, 2, 3}, {2, 2, 3}};
std::vector<int> b;
for(auto& vec : v){
std::copy(vec.begin(), vec.end(), std::back_inserter(b)); // performes single insertion at the end
}
std::copy
is bad style for inserting into a std::vector
. You insert it value by value at the end of the destination vector. This means potentially more reallocations and moves/copies as needed.
std::vector<std::vector<int>> vv = { { 1, 2, 3 },
{ 4, 5, 6 },
{ 7, 8, 9 } };
std::vector<int> v;
for (auto row : vv) {
for (auto el : row) {
v.push_back(el);
}
}
Same here. You resize it at every push_back
, that is absolutely not necessary!
I recommend you the use of std::vector::insert
. It performs some internal resizes by its own.
std::vector<std::vector<int>> v = {{1, 2, 3}, {2, 2, 3}};
std::vector<int> b;
for(auto& vec : v){
b.insert(std::cend(b), std::cbegin(vec), std::cend(vec));
}
This solution performs a resize before any insertion occurs. This will result in the best possible performance.
Here some testcode. Try it by your own:
#include <vector>
#include <chrono>
#include <iostream>
int main()
{
std::vector<int> v(100'000'000, 5);
auto start = std::chrono::steady_clock::now();
std::vector<int> b;
b.insert(std::cend(b), std::cbegin(v), std::cend(v));
auto end = std::chrono::steady_clock::now();
std::cout << "insert durtion:\t" << (end - start).count() << std::endl;
b = std::vector<int>();
start = std::chrono::steady_clock::now();
std::copy(std::cbegin(v), std::cend(v), std::back_inserter(b));
end = std::chrono::steady_clock::now();
std::cout << "copy durtion:\t" << (end - start).count() << std::endl;
b = std::vector<int>();
start = std::chrono::steady_clock::now();
for (auto el : v)
b.push_back(el);
end = std::chrono::steady_clock::now();
std::cout << "copy durtion:\t" << (end - start).count() << std::endl;
std::cin.ignore();
return 0;
}
This produces in x64 release in this output:
insert durtion: 132388657
copy durtion: 844505239
push_back durtion: 866565409
In the end, you could of course resize
the vector first and then start the copy, but I think that's the wrong way to deal with that, if in fact, the std::vector
already offers us this solution.