Suppose I have a class
struct Foo {double x; double y;}
and std::vector<Foo> xy;
I also have a function to pull out the x
members:
std::vector<double> bar(const std::vector<Foo>& xy);
which loops through each element of xy
.
Is there a way of using the C standard library so I can avoid an explicit for
loop?
CodePudding user response:
You can use std::transform
. E.g.
std::vector<double> bar(const std::vector<Foo>& xy) {
std::vector<double> rt;
rt.reserve(xy.size());
std::transform(std::begin(xy),
std::end(xy),
std::back_inserter(rt),
[](const Foo& f) { return f.x; });
return rt;
}
For comparison here's the version using range-based for loop. As @463035818_is_not_a_number commented it needs less typing.
std::vector<double> foo(const std::vector<Foo>& xy) {
std::vector<double> rt;
rt.reserve(xy.size());
for (auto const & f : xy) rt.push_back(f.x);
return rt;
}
CodePudding user response:
Using C 20's ranges offers a somewhat briefer alternative to std::transform
:
std::vector<double> filtered;
filtered.reserve(xy.size());
std::ranges::copy(
std::ranges::views::transform(xy, &Foo::x),
std::back_inserter(filtered));
Or, as pointed out by @StoryTeller, as an alternative and even briefer approach to the init-empty-and-back-insert, use a view to directly intitialize the filtered
vector (an approach that would allow it to be const
):
auto view = xy | std::ranges::views::transform(&Foo::x);
std::vector<double> const filtered(view.begin(), view.end());
CodePudding user response:
Well, behind the scenes there obviously has to be a loop somewhere. So it seems to me that the STL included for_each
for this exact type of problem.
We can write the Bar
function like so:
#include <algorithm>
auto Bar (const std::vector<Foo> & xy)
{
std::vector<double> bar;
auto extract_x = [&](const Foo & f){bar.push_back(f.x);};
std::for_each(xy.begin(), xy.end(), extract_x);
return bar;
}
By removing the auto
we can also do this with c 11
: Demo
However, I agree with others here that this doesn't seem more useful than a plain old loop. Maybe it's more useful in some real-world scenario - but I can't think of one.