I have a vector<A>
, A has a field A::foo.
I would like to create a vector which elements are the "foo's" of the previous vector. Sure I can iterate through the vector's elements, but is there a direct implementation in the STL or other major library ?
Asked
Active
Viewed 65 times
0

huehuehuehue
- 275
- 1
- 2
- 8
-
Do you mean "previous *element*" ? – Paul R Nov 28 '14 at 22:29
-
No, I mean if V is my original vector, the element at indice i of the new vector W is equal to V[i].foo – huehuehuehue Nov 28 '14 at 22:31
-
OK - maybe you should include your for loop version to make it clear what you want to do ? – Paul R Nov 28 '14 at 22:32
-
You want [`std::transform()`](http://en.cppreference.com/w/cpp/algorithm/transform). – David G Nov 28 '14 at 22:32
-
Internally I assume std::transform will be performing a loop though won't it? – Matt Coubrough Nov 28 '14 at 22:33
-
@Matt : I guess so but as a rule I don't use my code if there's already an implementation in a library (especially something like STL) somewhere. – huehuehuehue Nov 28 '14 at 22:35
-
@MattCoubrough there is no way to traverse a vector in less than `N` steps, so yes, it will perform a loop. – vsoftco Nov 28 '14 at 22:37
-
@huehuehuehue Fair enough and `std::transform` might be optimised for some container iteration (I like to use std library methods most of the time too)... But I hate it when simple code is obfuscated. I often look at code like `std::transform(....)` and have to scratch my head to work out what the hell it's doing, whereas `for(...) dosomething;` is immediately readable to anyone. – Matt Coubrough Nov 28 '14 at 22:41
-
@MattCoubrough I guess it's a matter of preference, if one is familiar with the Standard Library, then `std::transform` or `std::for_each` should be as clear as a `for` loop. But yes, if you just look at the (possible) implementation of `std::transform`, http://en.cppreference.com/w/cpp/algorithm/transform, it is nothing but a `while` loop. – vsoftco Nov 28 '14 at 22:42
3 Answers
3
Probably this should work
vector<A> vA; // this is your vector<A>, assumed to contain some `A`'s
...
vector<Foo> vFoo; // here is where we extract the Foo's
std::transform(std::begin(vA), std::end(vA), std::back_inserter(vFoo),
[](const A& param){return param.foo});

vsoftco
- 55,410
- 12
- 139
- 252
1
You can use std::transform
from <algorithm>
.
#include<algorithm>
std::vector<A> as;
// fill it
std::vector<A::foo_type> foos;
foos.resize(as.size());
std::transform(as.begin(), as.end(), foos.begin(), [](const &A) { return A.foo; });

marc
- 6,103
- 1
- 28
- 33
-
I'd like to add, that resize will default construct all elements of foo, which may or may not result in an observable overhead. – MikeMB Nov 28 '14 at 23:26
1
You can use std::transform, but in this case,i think a range based for loop is more readable and should be at least as efficient as using STL's algorithm.
EDIT: To illustrate my point:
struct Foo {};
struct Bar {
Foo foo;
};
int main() {
vector<Bar> bars(10);
vector<Foo> foos1, foos2, foos3;
foos1.reserve(bars.size());
for (const auto& e : bars) { // this will become 'for (e:bars)' in the future
foos1.push_back(e.foo);
}
foos2.resize(bars.size());
transform(bars.begin(), bars.end(), foos2.begin(), [](const Bar& bar) { return bar.foo; });
foos3.reserve(bars.size());
transform(bars.begin(), bars.end(), back_inserter(foos3), [](const Bar& bar){return bar.foo; });
}
In my opinion, the loop version is much easier to read (but I admit that this is probably a matter of taste).
Don't get me wrong, I really do like algorithms, but in very simple cases like this, their syntactic overhead just doesn't pull its weight.
EDIT2: Some processors have a gather instruction instruction. It would be interesting to see, whether a typical compiler would generate those and under which conditions.
-
-
Thats what I'd allso assume (of course y'd have to measure). Depending on how exactly you write the algorithmic version, the compiler is definitifely allowed to produce the same code, but in practice that doesn't necessarily mean it will. Using a algorithm adds another layer of abstraction, which the compiler may or may not be able to pierce in a specific case. It is however a myth, that the compiler will always generate the most efficient code for a given functionality independent of the used syntax. – MikeMB Nov 28 '14 at 23:19
-
In general yes. However, STL (or, better called, Standard Library) was design with zero overhead in mind. So in terms of asymptotic complexity, you definitely have the same constant in big O notation. As far as I know, even for small instance cases, the algorithms in the standard library should be pretty darn close to being optimal. – vsoftco Nov 28 '14 at 23:22
-
As far as big O is concerned you are completely right. However, two algorithms with the same complexity can (in theory) still differ in an order magnitude when running on actual hardware. Again, I totaly agree with you, that I wouldn't expect a difference. I just wanted to state that there might be a difference. – MikeMB Nov 28 '14 at 23:42