I'm using GCC 9.2.0 and boost 1.55.
I have 2 vectors:
vector< pair< string, int > > source;
vector< string > dest;
I need to transform the source
vector to the dest
, such that it should contain only string
elements of source
vector.
Is it possible using boost::push_back
and adaptors?
boost::range::push_back( dest, source | /* adaptor ??? */ );
Currently I have this workable code, but it should be changed:
transform( source.begin(), source.end(), back_inserter(dest), __gnu_cxx::select1st< std::pair< std::string, int > >() );
In your code, stringw is of the type char * and so it is not compatible with the vector you have defined.
Ways to copy a vector in C++ ... back_inserter()):- This is another way to copy old vector into new one. This function takes 3 arguments, first, the first iterator of old vector, second, the last iterator of old vector and third is back_inserter function to insert values from back. This also generated a deep copy.
Method 3 : By passing vector as constructor. At the time of declaration of vector, passing an old initialized vector, copies the elements of passed vector into the newly declared vector. They are deeply copied.
The different ways of creating a vector of strings in C++ are quite many. The most commonly used ways are illustrated in this article. An empty vector can be created first, before the string elements are added. When an element is added into a vector, the element is said to be pushed_back into the vector, because the element is inserted at the back.
Using the inbuilt function strcpy () from string.h header file to copy one string to the other. strcpy () accepts a pointer to the destination array and source array as a parameter and after copying it returns a pointer to the destination string.
To continue the trend of posting mimimal improvements:
Live On Compiler Explorer
#include <boost/range/adaptor/map.hpp>
#include <fmt/ranges.h>
using namespace std::string_literals;
using namespace boost::adaptors;
template <typename R>
auto to_vector(R const& range) {
return std::vector(boost::begin(range), boost::end(range));
}
int main() {
std::vector source {std::pair {"one"s,1},{"two",2},{"three",3}};
fmt::print("keys {}\nvalues {}\n",
source | map_keys,
source | map_values);
// if you really need the vectors
auto keys = to_vector(source | map_keys);
auto values = to_vector(source | map_values);
}
Prints
keys {"one", "two", "three"}
values {1, 2, 3}
You could use std::transform
and std::back_inserter
with a lambda instead:
#include <algorithm> // transform
#include <iterator> // back_inserter
std::transform(source.begin(), source.end(), std::back_inserter(dest),
[](auto& p) {
return p.first;
});
Here's a boost solution with the transformed
adaptor:
#include <boost/range/adaptor/transformed.hpp>
#include <iostream>
#include <string>
#include <utility>
#include <vector>
using boost::adaptors::transformed;
// define function object (so we can pass it around) emulating std::get
template<std::size_t N>
auto constexpr get = [](auto const& x){ return std::get<N>(x); };
int main()
{
// prepare sample input
std::vector<std::pair<std::string,int>> source{{"one",1},{"two",2},{"three",3}};
// the line you look for
auto dest = source | transformed(get<0>);
// dest is a vector on which we can iterate
for (auto const& i : dest) {
std::cout << i << '\n';
}
// if you really need it to be a vector
auto dest_vec = boost::copy_range<std::vector<std::string>>(dest);
}
Here's a solution using the range-v3 library:
auto dest = source
| ranges::views::keys
| ranges::to<std::vector<std::string>>;
Here's a demo.
In C++20, there's no std::ranges::to
, but you can still copy over the keys to dest
if it already exists:
std::ranges::copy(source | std::views::keys,
std::back_inserter(dest));
Here's a demo.
Note that this doesn't work in Clang trunk, which I assume is a bug.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With