Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I copy the strings in a vector<pair<string, int>> to vector<string>?

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 > >() );
like image 928
Alexandr Derkach Avatar asked Jan 19 '21 14:01

Alexandr Derkach


People also ask

Can we take string in vector?

In your code, stringw is of the type char * and so it is not compatible with the vector you have defined.

How to copy a vector in C++?

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.

How to copy elements of an initialized vector to another vector?

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.

How to create a vector of strings in C++?

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.

How to copy one string to another string in C++?

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.


Video Answer


4 Answers

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}
like image 162
sehe Avatar answered Oct 18 '22 04:10

sehe


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;
               });
like image 31
Ted Lyngmo Avatar answered Oct 18 '22 04:10

Ted Lyngmo


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);
}
like image 28
Enlico Avatar answered Oct 18 '22 03:10

Enlico


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.

like image 3
cigien Avatar answered Oct 18 '22 03:10

cigien