std::vector v1 {4,2,7,6,4,1};
std::vector v2 {3,0,0,0,0,3};
我想在条件v2=3的情况下获取v1中的值
我想要的结果[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::get<0>
的 lambda在其输入 std::pair
.
不幸的是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
的帮助下和 boost::hana::curry
人们可以将其写成 std::equal_to<>{}
的柯里化(Currying)版本。
auto constexpr equal_to = curry<2>(std::equal_to<>{});
并想出这个:
auto result = zip(v1, v2) | filter(compose(equal_to(3), get<1>))
| transform(get<0>);
巴里在评论中指出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
宏。
关于c++ - 如何从另一个 View 设置过滤器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71143460/