Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Initialize a container with iterator range of container with different type

Tags:

c++

c++11

stl

Let's say we have std::set<int> and we want to create a std::vector<int> with all values from that set:

std::set<int> set;
std::vector<int> vec( set.begin(), set.end() );

This is simple and elegant. But let's say I have a std::map<std::string,int> and I want to copy all values to std::vector<int>. Unfortunately there is no constructor, that accepts range of iterators and converter function. Why there is no such constructor provided? Is there another simple and elegant way to initialize one container with different type values?

like image 972
Slava Avatar asked Sep 03 '15 13:09

Slava


2 Answers

Use transform iterators:

#include <boost/iterator/transform_iterator.hpp>
#include <vector>
#include <map>

int main() {
    std::map<int, double> m;
    auto f = [](auto&& pair) { return pair.second; };
    std::vector<double>(boost::make_transform_iterator(m.begin(), f),
                        boost::make_transform_iterator(m.end(), f));
}

Alternatively, use boost::adaptors:

#include <boost/range/adaptor/map.hpp>
#include <vector>
#include <map>

int main() {
    std::map<int, double> m;
    auto range = boost::adaptors::values(m);
    std::vector<double>(range.begin(), range.end());
}

Or the same as above:

    auto v = boost::copy_range<std::vector<double> >(boost::adaptors::values(m));

Note that using vector's range constructor is more efficient than a solution involving back_inserter.

like image 76
Maxim Egorushkin Avatar answered Nov 01 '22 19:11

Maxim Egorushkin


With boost::transform_iterator:

#include <functional>
#include <boost/iterator/transform_iterator.hpp>

std::map<std::string, int> m{ {"a", 1}, {"b", 2} };
auto second = std::mem_fn(&std::map<std::string, int>::value_type::second);

std::vector<int> vec(boost::make_transform_iterator(std::begin(m), second)
                   , boost::make_transform_iterator(std::end(m), second));

DEMO

like image 44
Piotr Skotnicki Avatar answered Nov 01 '22 19:11

Piotr Skotnicki