How to create a vector from specific values ​​from an array?

I will start with the code:

#include <iostream>
#include <vector>
using namespace std;
struct A
{
    int color;

    A(int p_f) : field(p_f) {}
};
int main ()
{  
  A la[4] = {A(3),A(5),A(2),A(1)};
  std::vector<int> lv = {begin(la).color, end(la).color};//I would like to create vector from specific value from array la
  for (std::vector<int>::iterator it = fifth.begin(); it != fifth.end(); ++it) std::cout << ' ' << *it;
  return 0;
}

In general, I would like to create a vector from specific values ​​from an array. Since you can see that la is an array of A, and I would like to create a vector containing not the entire array of la, but only the color. vector (int), not vector (A), vector {3,5,2,1}, not A, but only int color. This can be done in C ++ 11. Thank you.

+4
source share
2 answers

That should work.

std::vector<int> lv;
std::transform(std::begin(la), std::end(la), std::back_inserter(lv), [](const A& a){
    return a.color;
});

There is also another way:

Restore your structure to get color from the method:

struct A
{
    int color;

    A(int p_f) : color(p_f) {}

    int getColor() const {
        return color;
    }
};

In this case you can use bind:

std::transform(std::begin(la), std::end(la), std::back_inserter(lv), std::bind(&A::getColor, std::placeholders::_1));

Or you can also use std::mem_fnfor a method that is a little shorter (thanks to @Piotr S.):

std::transform(std::begin(la), std::end(la), std::back_inserter(lv), std::mem_fn(&A::getColor));

std::mem_fn . getter:

std::transform(std::begin(la), std::end(la), std::back_inserter(lv), std::mem_fn(&A::color));
+10

:

namespace detail
{
    using std::begin;
    using std::end;

    template <typename Container, typename F>
    auto RetrieveTransformation(const Container& c, F f)
        -> std::vector<std::decay_t<decltype(f(*begin(c)))>>
    {
        // if `F` return `const T&`, we want `std::vector<T>`,
        // so we remove reference and cv qualifier with `decay_t`.
        //
        // That handles additionally the case of lambda
        // The return type of lambda [](const std::string&s) { return s;}
        // - is `const std::string` for msvc
        // - is `std::string` for for gcc
        // (Note that the return type rules have changed:
        // see http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1048)
        using F_Ret = std::decay_t<decltype(f(*begin(c)))>;
        std::vector<F_Ret> res;
        res.reserve(std::distance(begin(c), end(c)));
        for (const auto& e : c)
        {
            res.push_back(f(e));
        }
        return res;
    }

}

template <typename Container, typename F>
auto RetrieveTransformation(const Container& c, F f)
-> decltype(detail::RetrieveTransformation(c, f))
{
    return detail::RetrieveTransformation(c, f);
}

std::vector<int> lv = RetrieveTransformation(la, std::mem_fn(&A::getColor));
// or
// auto lv = RetrieveTransformation(la, [](const A&a){return a.color;});

Live Demo

+1

All Articles