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:
zipv1andv2,filterbased on the.secondof each element with the condition you liketransformto only retain the.firstof 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.
