Shedex
Shedex

Reputation: 131

C++ Copy elements from an object vector into a vector with this element

I want to copy the a values from the foos vector into another vector with just the int value. What's the fastest way to do this?

#include <vector>

struct Foo {
   int a;
};

int main() {
   std::vector<Foo> foos;
   for(int i = 0; i < 100; i++)
      foos[i].a = i;

   std::vector<int> somenumbers;
   //Fastest way to copy the ints from the struct into the somenumbers vector?  

   return 0;
}

Upvotes: 1

Views: 1286

Answers (3)

lubgr
lubgr

Reputation: 38267

There is also dense/one-liner solution when you comit to using Boost:

#include <boost/iterator/transform_iterator.hpp>

const std::vector<int> extraction{
    boost::make_transform_iterator(instances.cbegin(), std::mem_fn(&Foo::a)),
    boost::make_transform_iterator(instances.cend(), std::mem_fn(&Foo::a))
};

The function object that is passed to make_transform_iterator can be a lambda, too.

Upvotes: 0

ForEveR
ForEveR

Reputation: 55887

What do you mean fastest? Just loop, or algorithm, or something else. For example:

std::transform
(
    foos.begin(), foos.end(), std::back_inserter(somenumbers),
    [](const Foo& v) { return v.a; }
);

Also, since you know size of vector - you should callreserve.

Upvotes: 3

Vittorio Romeo
Vittorio Romeo

Reputation: 93264

somenumbers.reserve(foos.size());
for(const auto& f : foos) somenumbers.emplace_back(f.a);

If you're doing this operation multiple times in your codebase, introduce an abstraction:

template <typename TRange, typename TF>
auto map_vector(TRange&& range, TF&& f)
{
    using type = std::decay_t<decltype(f(*std::begin(range)))>;

    std::vector<type> result;
    result.reserve(range.size());

    for(auto&& x : range) result.emplace_back(forward_like<TRange>(x));
    return result;
}

(forward_like can be found here.)

Usage:

auto somenumbers = map_vector(foos, [](const auto& x){ return x.a; });

Upvotes: 3

Related Questions