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.
  • 3,007
  • 3
  • 22
  • 37
Shedex
  • 121
  • 2
  • 12
  • 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
  • 171,901
  • 28
  • 288
  • 402
ForEveR
  • 55,233
  • 2
  • 119
  • 133
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
  • 90,666
  • 33
  • 258
  • 416
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
  • 32,622
  • 4
  • 31
  • 60
lubgr
  • 37,368
  • 3
  • 66
  • 117