在容器上迭代地应用 range-v3 views::filter
Posted
技术标签:
【中文标题】在容器上迭代地应用 range-v3 views::filter【英文标题】:Iteratively apply range-v3 views::filter on a container 【发布时间】:2021-11-18 12:06:22 【问题描述】:在以下代码 sn-p 的for
循环中,我正在尝试应用views::filter
。但是会导致类型不匹配和赋值错误。
#include <iostream>
#include <vector>
#include <numeric>
#include <range/v3/all.hpp>
int main()
int limit =100;
std::vector<int> numbers(100);
std::iota(numbers.begin(), numbers.end(), 1);
auto results = numbers | ranges::views::filter([](int n) return n != 1; );
int sqrt_limit = std::sqrt(limit);
for (int i = 2; i <= sqrt_limit; i++)
results = results | ranges::views::filter([i](int n) return n == i
|| n % i != 0; );
错误 C2679 二进制“=”:未找到采用“ranges::filter_viewranges::filter_view<:ref_view> 类型的右侧操作数的运算符>,Arg>,main::
>' (或没有可接受的转换)`
所以基本上我怎样才能在numbers
上应用views::filter
,在results
上分配结果,然后在results
上应用views::filter
,然后再次在results
上分配结果?
std::vector<int> numbers(100);
std::iota(numbers.begin(), numbers.end(), 1);
auto results = numbers | ranges::views::filter([](int n) return n != 1; );
results = results | ranges::views::filter([i](int n) return n == 2
|| n % 2 != 0; );
【问题讨论】:
【参考方案1】:在您的示例中,results | ranges::views::filter
的返回类型与results
不同,因此您不能将其分配给results
。
另一种方法是使用ranges::to
将每个结果转换为vector
并将其分配给之前的结果:
std::vector<int> numbers(100);
std::iota(numbers.begin(), numbers.end(), 1);
auto results = numbers
| ranges::views::filter([](int n) return n != 1; )
| ranges::to_vector;
results = results
| ranges::views::filter([](int n) return n == 2|| n % 2 != 0; )
| ranges::to_vector;
Demo.
【讨论】:
谢谢。我不知道 range::to .【参考方案2】:views::filter
返回的类型与传入的范围类型不同。您可以在每次过滤后应用ranges::to
创建一个向量,但这会很昂贵。对于这个问题,即使用筛子生成素数,使用 Eager 算法是有意义的。
您应用的第一个过滤器是不必要的;只需在 2 处开始 iota
,因为那是第一个素数。
auto results = numbers;
那么当还有素数要筛选的时候
auto end = std::end(results);
for (auto begin = std::begin(results); begin != end; begin++)
end = std::remove_if(begin + 1, end, // *begin is prime by definition, so skip it
[i = *begin](int n)
return n % i == 0; // remove multiples of the prime
);
// erase all the composite numbers
results.erase(end, std::end(results));
上面的循环也在做一个过滤器,但是使用remove
,所以这个条件必须被否定。此外,由于跳过了素数本身,因此 lambda 不需要检查是否为 n == i
。
demo
【讨论】:
以上是关于在容器上迭代地应用 range-v3 views::filter的主要内容,如果未能解决你的问题,请参考以下文章