如何从另一个视图设置过滤器?
how to set filter from another view?
std::vector v1 {4,2,7,6,4,1};
std::vector v2 {3,0,0,0,0,3};
我想获取 v1 中的值,条件为 v2=3
我想要的结果 [4,1]
我试过使用过滤器,但它似乎只适用于指定的值。
auto rng = v1 | ranges::views::filter([](int x){return ...;});
如果不使用 for 循环,我如何做到这一点?
应该是这样的:
zip
v1
和 v2
,
filter
根据每个元素的.second
加上你喜欢的条件
transform
只保留存活元素的 .first
#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]
}
一些改进
请注意 [](auto pair){ return pair.first; }
只是一个在其输入 std::pair
上运行 std::get<0>
的 lambda。
不幸的是std::get<0>
不能独立存在,因为它有几个重叠部分(对于std::pair
、std::tuple
、std::array
、std::variant
).
简化代码的一种方法是
#include <boost/hof/lift.hpp>
然后定义
template<std::size_t N>
auto constexpr get = BOOST_HOF_LIFT(std::get<N>);
以便您可以轻松地通过 get<0>
。
鉴于此,在 boost::hana::compose
and boost::hana::curry
的帮助下,可以将此写成 std::equal_to<>{}
的柯里化版本
auto constexpr equal_to = curry<2>(std::equal_to<>{});
然后想出这个:
auto result = zip(v1, v2) | filter(compose(equal_to(3), get<1>))
| transform(get<0>);
Barry在评论中指出transform(get<0>)
其实就是ranges::views::keys
,所以代码可以进一步简化:
auto result = zip(v1, v2) | filter(compose(equal_to(3), get<1>))
| keys;
在另一条评论中指出了一些我从未想过的事情:filter
也有一个投影函数,所以 filter(compose(equal_to(3), get<1>))
与 filter(equal_to(3), get<1>)
做同样的工作:
auto result = zip(v1, v2) | filter(equal_to(3), get<1>)
| keys;
最后,get<1>
是 elements<1>
(不管是什么地方,我还没有找到它 :D),所以我们可以不用 Boost.Hof 的 BOOST_HOF_LIFT
宏.
std::vector v1 {4,2,7,6,4,1};
std::vector v2 {3,0,0,0,0,3};
我想获取 v1 中的值,条件为 v2=3
我想要的结果 [4,1]
我试过使用过滤器,但它似乎只适用于指定的值。
auto rng = v1 | ranges::views::filter([](int x){return ...;});
如果不使用 for 循环,我如何做到这一点?
应该是这样的:
zip
v1
和v2
,filter
根据每个元素的.second
加上你喜欢的条件transform
只保留存活元素的.first
#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]
}
一些改进
请注意 [](auto pair){ return pair.first; }
只是一个在其输入 std::pair
上运行 std::get<0>
的 lambda。
不幸的是std::get<0>
不能独立存在,因为它有几个重叠部分(对于std::pair
、std::tuple
、std::array
、std::variant
).
简化代码的一种方法是
#include <boost/hof/lift.hpp>
然后定义
template<std::size_t N>
auto constexpr get = BOOST_HOF_LIFT(std::get<N>);
以便您可以轻松地通过 get<0>
。
鉴于此,在 boost::hana::compose
and boost::hana::curry
的帮助下,可以将此写成 std::equal_to<>{}
auto constexpr equal_to = curry<2>(std::equal_to<>{});
然后想出这个:
auto result = zip(v1, v2) | filter(compose(equal_to(3), get<1>))
| transform(get<0>);
Barry在评论中指出transform(get<0>)
其实就是ranges::views::keys
,所以代码可以进一步简化:
auto result = zip(v1, v2) | filter(compose(equal_to(3), get<1>))
| keys;
在另一条评论中指出了一些我从未想过的事情:filter
也有一个投影函数,所以 filter(compose(equal_to(3), get<1>))
与 filter(equal_to(3), get<1>)
做同样的工作:
auto result = zip(v1, v2) | filter(equal_to(3), get<1>)
| keys;
最后,get<1>
是 elements<1>
(不管是什么地方,我还没有找到它 :D),所以我们可以不用 Boost.Hof 的 BOOST_HOF_LIFT
宏.