1

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;
}
Onur A.
  • 2,981
  • 3
  • 21
  • 36
Shedex
  • 101
  • 1
  • 11
  • use [std::transform](http://en.cppreference.com/w/cpp/algorithm/transform), and then profile to make sure it is actually a bottleneck before trying to optimize it. – Borgleader Feb 22 '17 at 13:58
  • 2
    Whatever you do, call `reserve` on `somenumbers` before you add anything to it. – NathanOliver Feb 22 '17 at 13:59

3 Answers3

3

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.

NathanOliver
  • 161,918
  • 27
  • 262
  • 366
ForEveR
  • 53,801
  • 2
  • 106
  • 128
3
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; });
Community
  • 1
  • 1
Vittorio Romeo
  • 86,944
  • 30
  • 238
  • 393
0

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.

Alan Birtles
  • 27,579
  • 4
  • 25
  • 50
lubgr
  • 35,985
  • 3
  • 62
  • 111