std::vector v1 {4,2,7,6,4,1};
std::vector v2 {3,0,0,0,0,3};
I want to get the values in v1 with the condition v2=3
my desired result [4,1]
I tried with filter but it seems to work only with a specified value.
auto rng = v1 | ranges::views::filter([](int x){return ...;});
How can I do this without using for-loop?
CodePudding user response:
Should be something along these lines:
zip
v1
andv2
,filter
based on the.second
of each element with the condition you liketransform
to only retain the.first
of the survived elements
#include <iostream>
#include <range/v3/view/filter.hpp>
#include <range/v3/view/transform.hpp>
#include <range/v3/view/zip.hpp>
using namespace ranges::views;
int main() {
std::vector v1 {4,2,7,6,4,1};
std::vector v2 {3,0,0,0,0,3};
auto result = zip(v1, v2) | filter([](auto pair){ return pair.second == 3; })
| transform([](auto pair){ return pair.first; });
std::cout << result << std::endl; // prints [4,1]
}
Some improvement
Notice that [](auto pair){ return pair.first; }
is simply a lambda that runs std::get<0>
on its input std::pair
.
Unfortunately std::get<0>
can't stand on its own, because there are several overlods of it (for std::pair
, std::tuple
, std::array
, std::variant
).
One way to streamline the code would be to
#include <boost/hof/lift.hpp>
and then define
template<std::size_t N>
auto constexpr get = BOOST_HOF_LIFT(std::get<N>);
so that you can pass get<0>
around easily.
Given this, and with the help of boost::hana::compose
and boost::hana::curry
one can write this a curried version of std::equal_to<>{}
auto constexpr equal_to = curry<2>(std::equal_to<>{});
and come up with this:
auto result = zip(v1, v2) | filter(compose(equal_to(3), get<1>))
| transform(get<0>);
Barry pointed out in a comment that transform(get<0>)
is actually ranges::views::keys
, so the code can be further simplified:
auto result = zip(v1, v2) | filter(compose(equal_to(3), get<1>))
| keys;
In another comment was pointed out something that I never think about: filter
takes a projection function too, so filter(compose(equal_to(3), get<1>))
does the same job as filter(equal_to(3), get<1>)
:
auto result = zip(v1, v2) | filter(equal_to(3), get<1>)
| keys;
And finally, get<1>
is elements<1>
(wherever that is, I haven't found it yet :D), so we can do without Boost.Hof's BOOST_HOF_LIFT
macro.