首页 > 编程语言 >浅谈 c++20 ranges 的用法

浅谈 c++20 ranges 的用法

时间:2022-11-11 20:00:24浏览次数:64  
标签:std 20 浅谈 int 适配器 ranges take 端点 范围

ranges 库是 c++20 开始具有的语法,对应的头文件是 #include<ranges>。为了防止 CE 我一般都这么写:

#if __cplusplus>=202002L
#include<ranges>
using namespace std::views;
#endif

ranges 最有用的操作是 for(int i:v) 这种 for 循环。如果想反向输出直接 for(int i:v|reverse) 就可以了。

另外还有一些其他的范围适配器。

  • filterfilter([](int x){return x&1;}) 表示只取范围内的奇数。
  • transformtransform([](int x){return x*x;}) 表示取范围内数前先平方。
  • taketake(x) 表示取范围前 \(x\) 个。
  • take_whiletake_while([](int x){return x&1;}) 表示一直取直到取到偶数为止。
  • taketake(x) 表示不取范围前 \(x\) 个。
  • take_whiletake_while([](int x){return x&1;}) 表示一直不取直到取到偶数为止。
  • reversereverse 表示反向迭代序列。
  • elementselements(x) 表示只取 tuple 的第 \(x+1\) 个元素。
  • keyskeys 表示只取 pairfirst
  • valuesvalues 表示只取 pairsecond
  • adjacentadjacent(x) 表示取每个长度为 \(x\) 的 tuple,是引用。

上面这些都是用 operator| 和范围适配器连接起来的,还有几个另外的范围适配器:

  • spiltspilt(v,x),这个的返回值是一个可以用范围遍历的东西,也就是范围适配器。
std::vector v={20,1,12,4,1,3,10,1};
for(auto i:split(v|reverse,1)){
	for(int k:i)cout<<k<<' ';
	cout<<'\n';
}
  • countedcounted(p,x)是以 \(p\) 为初始迭代器向后拓展 \(x\) 的可迭代对象。
std::vector v={20,1,12,4,1,3,10,1};
for(int i:counted(vec.begin()+1,3))
	cout<<i<<' ';

  • join:直接连接,表示这个范围适配器拉平一次的结果。如果这么写 \(i\) 的类型是 vector<int> 而不是 int,只会拉平一次!所以会 CE。
std::vector<std::vector<std::vector<int>>>v{{{20,1},{12}},{{4,1},{3,10,1}}};
for(auto i:v|join)cout<<i<<' ';
  • join_with:和 join 效果一样,join_with(x) 表示每次拉平一块后加入一个 \(x\)。
  • zip:把几个范围适配器每次取一个组成 tuple 的范围适配器。这里直接放这里的代码,不知道为什么没有 zip
auto x=std::vector{1,2,3,4};
auto y=std::list<std::string>{"α","β","γ","δ","ε"};
auto z=std::array{'A','B','C','D','E','F'};
for(std::tuple<int&,std::string&,char&>i:zip(x,y,z))
	cout<<get<0>(i)<<' '<<get<1>(i)<<' '<<std::get<2>(i)<<'\n',
	std::get<char&>(i)+=('a'-'A');
cout<<'\n';
for(auto i:z)cout<<i<<' ';
  • slideslide(x) 返回范围适配器,枚举左端点,右端点是左端点移 \(x\) 后的结果。
  • chunkchunk(x) 返回范围适配器,枚举左端点,右端点是左端点移 \(x\) 后的结果,但是下一个左端点是这次的右端点的下一个。
  • chunk_bychunk_by(x) 表示如果两个元素不满足 \(x\) 的关系,就在这里割一刀,每次返回两刀之间的范围适配器。
  • empty:产生一个空的范围适配器。
  • singlesingle(x) 能产生只有 \(x\) 这个元素的范围适配器。
  • iotasingle(x,y) 重复 \(x\),每次累加,如果大于等于 \(y\) 就退出,\(y\) 不写就一直循环下去。
  • istreamistream<t>(x) 从 \(x\) 的流里以 \(t\) 的类型构造,for(int i:istream<int>(cin))
  • repeatrepeat(x,y) 重复 \(x\) 的值 \(y\) 次,\(y\) 不写表示重复。

另外所有 ranges 都具有惰性求值的,不去访问就没有时间复杂度。

std::vector v1={1,3,4,2,5};
auto v2=v1|reverse|transform([](int x){return x*x;});

这样就可以产生一个是 v1 反向的,每个数都是 v1 平方的范围适配器。

标签:std,20,浅谈,int,适配器,ranges,take,端点,范围
From: https://www.cnblogs.com/bxjz/p/ranges.html

相关文章

  • 【日总结】2022.11.11
    到衡实了今天期中考完,考的很垃圾,没啥可总结的,补一道前几天的题的口胡2022NOIPA层联测19T4术劣在地理自习上想完了细节。感觉智力很下降,经典trick没有想起来。......
  • 2022NOIP A层联测25 惊喜二十二 K-构造 函数的权力 最大可达流形
    T1[计数类DP/转化]给出2个排列p,q,长度都是n,其中p完全给出,\(\existspi=0\Leftrightarrowi位置可以填任意[1,n]之间的数使得q构成排列\),问长度是n的01串S的个数,使得存在2*......
  • 【2022-11-11】luffy项目实战(六)
    一、登录注册页面Header.vue<template><divclass="header"><divclass="slogan"><p>老男孩IT教育|帮助有志向的年轻人通过努力学习获得体面的工作和生......
  • 浅谈Object类和包装类
    Object类简介Object类接收任意类型的对象toString方法equals方法包装类简介包装类的应用Object类简介Object类是java的一个内置类,属于java.lang包,此包下的所有类......
  • 2022-11-11
    2D: 2H:  20F:   总结:预计转2D下跌,所以做空2H上涨中枢形成,等待出中枢20F,前一波上涨是20F级别,最近一波上涨级别如果不少于20F且两波背驰,开空 ......
  • 2010 Principles on the Security of AES against First and Second-Order Differenti
    一、对于AES算法的DPA攻击准则(无防护措施下的AES实现)(1)在第3轮列混淆前任意中间值可以用于一阶DPA攻击,该攻击将明文的0,3或15比特固定(2)在第7轮轮......
  • 2022-11-11 Acwing每日一题
    本系列所有题目均为Acwing课的内容,发表博客既是为了学习总结,加深自己的印象,同时也是为了以后回过头来看时,不会感叹虚度光阴罢了,因此如果出现错误,欢迎大家能够指出错误,我......
  • 软件工程 张雯雯 223201062202
    2.1实验过程2.1.1实验代码给出博客园截图和网址,并附上github的代码地址。GitHub代码地址: 2.1.2实验过程(1) 本人角色自己在本次结对项目中所担任角色,以及结对伙......
  • 【题解】P2260 [清华集训2012]模积和(数学,整除分块)
    【题解】P2260[清华集训2012]模积和比较简单的一道推式子的题。(清华集训居然会出这种水题的吗)题目链接P2260[清华集训2012]模积和题意概述求\[\sum_{i=1}^{n}\sum......
  • 2022赛前模测 提高组 第一场
    2022赛前模测提高组第一场Chain题面描述:现有\(n\)个不超过\(10^6\)的合数,每个均可表示为\(a=p*q\)(为两个互异素数)。若\(a=p_1*q_1(p_1<q_1),b=p_2*q_2(p_2<q_2)......