If I have a 2D vector of size n x m and I want to create a 1D vector of size n with all the elements in column 0 of 2D vector, how can I achieve this with one line of code?
Basically, I want to minimize last 3 lines of code into 1.
vector<int> res;
for (auto i:orders) res.push_back(i[1]);
return res;
orders is a 2D vector:
vector<vector<int>> orders;
CodePudding user response:
This could be a way:
- Create a new vector with a size equals to the original vector (only that this won't be a vector of vectors of int, just a vector of int).
- Then fill it with the contents of
v[row][0]
,v
being the original vector.
#include <algorithm> // generate
#include <iostream> // cout
#include <vector>
int main()
{
std::vector<std::vector<int>> v{ {1, 2}, {3, 4}, {5, 6} };
std::vector<int> w(v.size());
std::generate(std::begin(w), std::end(w), [row=0, &v]() mutable { return v[row ][0]; });
for (auto&& i : w) { std::cout << i << " "; } std::cout << "\n";
}
In a bit more generic way, still using vector of vectors though:
#include <algorithm> // generate
#include <iostream> // cout
#include <vector>
template <typename T>
auto slice_column(const std::vector<std::vector<T>>& v, size_t col)
{
std::vector<T> ret(v.size());
std::generate(std::begin(ret), std::end(ret), [row=0, &v, &col]() mutable { return v[row ][col]; });
return ret;
}
int main()
{
std::vector<std::vector<int>> v{ {1, 2}, {3, 4}, {5, 6} };
auto w{ slice_column(v, 0) };
for (auto&& i : w) { std::cout << i << " "; } std::cout << "\n";
}
CodePudding user response:
I want to create a 1D vector of size n with all the elements in column 0 of 2D vector
This answer focuses on the above.
Create a view over the first element in each vector and return {begin(), end()}
for that view to create the resulting vector
from those iterators:
#include <ranges> // std::views::transform
#include <vector>
template<class T>
std::vector<T> jimOrders(const std::vector<std::vector<T>>& orders) {
auto view = orders | std::views::transform([](const auto& i) { return i[0]; });
return {view.begin(), view.end()};
}