将带有函数和运算符的Raku-grep闭包移植到C++中

Porting a Raku grep closure with functions and operators into C++

本文关键字:闭包 C++ Raku-grep 函数 运算符      更新时间:2024-05-09

这是一个示例Raku代码,它使用grep闭包,示例标准由函数和逻辑运算符组成:

print "$_, " for ( grep  { is-prime $_ and $_ > 5 and not ($_ == 11 or $_ == 13) }, 1..20);
# Output is: 7, 17, 19

我想使用vectorlistlambda将其移植到C++中,在其中我可以设置示例标准。这是我的看法:

#include <iostream>
#include <map>
#include <vector>
#include <algorithm>
#include <random>
using namespace std;
bool isPrime(int num){
bool flag=true;
for(int i = 2; i <= num / 2; i++) {
if(num % i == 0) {
flag = false;
break; } }
return flag;}
int main(){
vector<int> a(20);
iota(begin(a), end(a), 1); 
vector<int> b(a.size());
auto end = copy_if(cbegin(a), cend(a), begin(b),
[](int x) { return isPrime(x) & ( x > 5 ) & !( (x == 11) | (x == 13) ); });
b.erase(end, b.end()); 
for (auto n: b) 
cout << n << 'n';
// Output is: 7, 17, 19
}

我试图在不使用copy_if的情况下制作它,即使用find_if,这样我就不必创建辅助向量b

for (auto x : a) cout << find_if(a.begin(), a.end(), [x](){return isPrime(x) & ( x > 5 ) & !( (x == 11) | (x == 13));});

但它不起作用。怎么做?

Perl在这里所称的grep在C++(以及其他一些上下文(中被称为过滤器。C++20提供std::ranges::filter_view用于此目的,但由于此问题标记为C++17…

您尝试的find_if方法没有意义,因为它仍然涉及对每个元素进行迭代(并要求库使用不带参数的"谓词"进行搜索(。

当然可以使用std::find_if将迭代器依次推进到每个感兴趣的新值:

for(auto i=a.begin(),e=a.end();i!=e;
i=find_if(i+1,e,[](int x)
{return isPrime(x) & ( x > 5 ) && !( (x == 11) || (x == 13));})
cout << n << 'n';

(注意逻辑运算符而不是逐位运算符。(由于这涉及到显式循环(跟踪每次搜索的开始位置(,因此它并不比考虑每个元素的纯命令式方法好:

for(auto n : a)
if(isPrime(x) && ( x > 5 ) && !( (x == 11) || (x == 13) ))
cout << n << 'n';

也许在C++20之前避免复制的最自然的方法是使用CCD_;序列":

copy_if(cbegin(a), cend(a), std::ostream_iterator<int>(std::cout, "n"),
[](int x) { return isPrime(x) && ( x > 5 ) && !( (x == 11) || (x == 13) ); });

在C++20之前,没有等效于1..20std可用于for ( : ),而是使用for (;;)

auto criteria = [](int x){ return isPrime(x) && (x > 5) && (x != 11) && (x != 13); };
for (int x = 1; x <= 20; ++x) {
if (criteria(x)) {
std::cout << x;
}
}