哪些集合不能使用迭代器_Rust能力养成之(6):集合体与迭代器
前言
上一篇,介绍了Rust语言的
- 结构体的函数和方法实现
- 枚举的函数和方法实现
- 模块简介
这一篇,我们介绍一下Rust中的复杂数据类型
- 集合体
- 数组
- 元组
- 向量
- 哈希
- 切片
- 迭代器
集合体(Collections)
在编程实践中,显然会遇到处理“组团”数据的情况,这自然需要复杂数据类型来呼应,那么集合体就出现了,Rust提供了多种这样的内建类型。
本节,首先看下数组和元组。然后,看下标准库中的动态集合类型,主要介绍向量vectors(列表list)和哈希图hashmaps(键/值,key/value)。最后,引出切片slices,以其进入复杂数据的内部一看究竟。
数组(Arrays)
先从Rust数组开始,与其他语言的数组类似,要求定长和同类型,用[T, N]表示,其中T为任意类型,N为数组中元素的个数,不能是一个变量,建议使用常量usize值。
看下这个代码实例:
// arrays.rsfn main() { let numbers: [u8; 10] = [1, 2, 3, 4, 5, 7, 8, 9, 10, 11]; let floats = [0.1f64, 0.2, 0.3]; println!("Number: {}", numbers[5]);println!("Float: {}", floats[2]);
}
以上代码结果为
第4,5行分别给出了两种初始化数组的方式,第一种是标准方式,第二种是把类型放在一个元素的位置并加上前缀指定类型,显得很灵活。
元组(Tuples)
与数组不同的是,元组中可以存放不同类型的数据,因此是一种异质性的集合体,在为函数传参或者做返回值方面用处颇大。
// tuples.rsfn main() { let num_and_str: (u8, &str) = (40, "Have a good day!");println!("{:?}", num_and_str);let (num, string) = num_and_str;println!("From tuple: Number: {}, String: {}", num, string);
}
以上代码结果为
可见,第4-5行,定义并提取一个元组的值,第6-7行,对元组进行分解赋值。
向量(Vectors)
比起数组,向量的好处,是不必提前定义内容和长度,这是一种与时俱进的类型,显然是动态的,在栈上分配空间,可以通过调用Vec::new构造函数或使用Vec ![]宏进行创建。
好,上代码:
// vec.rsfn main() {let mut numbers_vec: Vec<u8> = Vec::new(); numbers_vec.push(1); numbers_vec.push(2); let mut vec_with_macro = vec![1]; vec_with_macro.push(2);let _ = vec_with_macro.pop(); // value ignored with `_`let message = if numbers_vec == vec_with_macro {"They are equal"} else {"Nah! They look different to me"};println!("{} {:?} {:?}", message, numbers_vec, vec_with_macro);
}
简单分析一下,这里分别用两种方式创建向量:
第4行的number_vec 和 第8行的vec_with_macro ;而后利用push()和pop()进行增删数据。
在这里还有诸多用法,读者可以自己再跑跑。
std::vec::Vec - Rustdoc.rust-lang.org
实际上向量也可以利用for 循环来体现其迭代器性质。
上述代码结果如下
哈希(Hashmaps)
Rust不会忘记提供映射格式来存储键值数据的,相关功能来自于标准库std::collections模块:
名为HashMap,通过HashMap::new函数来创建。
看下代码:
// hashmaps.rsuse std::collections::HashMap; fn main() { let mut fruits = HashMap::new(); fruits.insert("apple", 3);fruits.insert("mango", 6);fruits.insert("orange", 2);fruits.insert("avocado", 7);for (k, v) in &fruits {println!("I got {} {}", v, k);}fruits.remove("orange");let old_avocado = fruits["avocado"];fruits.insert("avocado", old_avocado + 5);println!("nI now have {} avocados", fruits["avocado"]);
}
我们读一下:
- 第3行,载入需要的模块std::collections::HashMap
- 第6行,创建新的哈希图变量,fruits
- 第7-10行,为该变量赋键值,使用inser方法
- 第11-13行,打印赋值结果,涉及for循环,这里面是循环变量是元组(k,v),分别对应keys()和values()两种方法,面向引用变量&fruits进行迭代
- 第15行,删除一个键,一对键值同时删除
- 第16行,创建一个简单变量old_avocado,取得avocado在fruits中的数值
- 第17行,为fruits中的avocado插入新值
- 第18行,打印修改后的fruits["avocado"]数值
上述代码结果如下
一般而言,用于对HashMap类型的键进行散列的算法基于Robin hood开放寻址方案,但可以根据用例和性能使用自定义散列器替换
切片(Slices)
切片是一种”瞥见“集合类型数据内容的通用方法,大多数用例在于获得对集合类型中特定范围项的只读访问。
切片基本上是一个指针或引用,指向由其他变量现所拥有的集合类型中的一个连续区间。
在底层,切片是指向堆栈或堆中某处数据的胖指针(fat pointer),这意味着切片,除了包含指向该数据的指针,还拥有指向多少数据的信息。
切片用&[T]表示,其中T是类型,用法与数组很相似。
我们看下代码:
// slices.rsfn main() {let mut numbers: [u8; 4] = [1, 2, 3, 4];{let all: &[u8] = &numbers[..];println!("All of them: {:?}", all);}{let first_two: &mut [u8] = &mut numbers[0..2];first_two[0] = 100;first_two[1] = 99;}println!("Look! I can modify through slices: {:?}", numbers);
}
我们读一下代码:
- 第4行,创建一个可变绑定类型的数组变量 numbers
- 第6行,创建&[u8]类型的切片,并使用&numbers指向数组number
- [..]意味着全部引用该数组的数据
- 之所以使用&是由于切片不能把数组数据拿来,只能引用,根源在于切片是unsized types,而这又是一个后续要详细谈的内容,读者莫急
- 第11行,创建切片引用该数组的前两个位置
- 第12-16行,通过切片改变原来数组的值,打印结果,成功
上述代码结果如下
不知道读者是否看到,代码中的第5,8,10,14行中有两组大括号,用来与不可变绑定变量进行区隔,否则不会通过编译的,这一点依然要到后续篇章才能讲清楚。
迭代器(Iterators)
迭代器不是什么新概念,其出现是以一种高效的方式过一下集合体中的元素,很多语言中都有,比如Python的iter(some_list) 和C++的 vector.begin() 。
其优势体现在
- 提供一种优雅高级的遍历集合体数据的方式,而不用手写for循环了
- 迭代器不会直接读取全部数据,而是采取懒惰(lazy)的方式,体现在
- 如果只需要一个数据,那么就只访问该条数据
- 还可以与多个转换操作(multiple transformation operations)链接在一起,
- 比如根据条件筛选元素,并且在需要时才对转换进行计算
- 提供next()方法,为读取下一条做准备
在Rust中,迭代器可以是实现其特性的任何类型,然后可以在for循环中使用此类型遍历其项,并实现在大多数标准库集合类型上,如Vector、HashMap、BTreeMap等等,也可以实现在自定义的类型上。
处理Rust中的集合类型时,迭代器是常用器械。实际上,Rust的for循环就被退化并隐藏为一个常规的包含next方法的match表达式,调用遍历对象。
此外,可以通过调用iter()或into_iter()将大多数集合类型转换为迭代器。
后边篇章还要结合新的知识点来进一步介绍迭代器的内容,本篇先到这里,很庆幸吧,这一节没有代码。
结语
本篇讲过了集合体和迭代器,里面蕴含了一些尚未揭开的谜团,请读者耐心一下,后面都会一一说明。
下一篇会先讲一下Rust中的项目管理。
主要参考和建议读者进一步阅读的文献
The Rust Programming Languagedoc.rust-lang.org
Rust编程之道,2019, 张汉东
The Complete Rust Programming Reference Guide,2019, Rahul Sharma,Vesa Kaihlavirta,Claus Matzinger
Hands-On Data Structures and Algorithms with Rust,2018,Claus Matzinger
Beginning Rust ,2018,Carlo Milanesi
Rust Cookbook,2017,Vigneshwer Dhinakaran
哪些集合不能使用迭代器_Rust能力养成之(6):集合体与迭代器相关推荐
- rust有准星_Rust能力养成系列之(2):功能抽象
前言 上一篇,介绍了上一篇,介绍了Rust语言的安装与编译 基本数据类型 变量声明和不可变绑定 这其中已经蕴含着Rust精华的成分了.本篇内容将涉及常规函数 闭包 字符串 函数(Function) 一 ...
- rust门卡有什么用_Rust能力养成之(10)用Cargo进行项目管理:扩展 调用与优化
前言 上一篇我们讲了Cargo运行测试 Cargo运行实例 Cargo工作空间 当然,Cargo也能够进行扩展,合并外部工具以增强开发体验,在设计上,其可扩展性已经达到非常丰富和恰当的程度.Cargo ...
- javascript迭代器_JavaScript符号,迭代器,生成器,异步/等待和异步迭代器-全部简单解释...
javascript迭代器 by rajaraodv 通过rajaraodv JavaScript符号,迭代器,生成器,异步/等待和异步迭代器-全部简单解释 (JavaScript Symbols, ...
- STL中迭代器的作用,有指针为何还要迭代器
请你来说一下STL中迭代器的作用,有指针为何还要迭代器 参考回答: 1.迭代器 Iterator(迭代器)模式又称Cursor(游标)模式,用于提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴 ...
- 迭代器 组合模式 java_设计模式(九)迭代器模式与组合模式
迭代器与组合模式 面对不同的问题,自然会用到不同的数据结构,甚至相同的问题也可以用不同的数据结构来实现.比如数组和ArrayList都可以构造一个列表. 但当想获得集合内的元素时,直接的取用就会涉及到 ...
- 大话设计模式之爱你一万年:第二十章 行为模式:迭代器模式:让遍历标准化:1. 迭代器模式
如果要问java中使用最多的一种模式,答案不是单例模式,也不是工厂模式,更不是策略模式,而是迭代器模式,先来看一段代码吧: /*** 测试Iterator** @author 悟纤「公众号Spring ...
- java迭代器的原理_小学生之Java中迭代器实现的原理
一. 引言 迭代这个名词对于熟悉Java的人来说绝对不陌生.我们常常使用JDK提供的迭代接口进行java collection的遍历: Iterator it = list.iterator(); w ...
- Python zip() 函数--多个迭代器取元素组合成一个新的迭代器
目录 Python3 元组 描述 语法 实例 1.当zip()函数中只有一个参数时 2.当zip()函数有两个参数时 3.zip()函数的应用 Python3 元组 Python 的元组与列表类似,不 ...
- C++日记——Day5:迭代器、begin()/end(),rbegin()/rend()、迭代器失效、const_iterator
迭代器简介 迭代器是一种遍历容器内元素的一种数据类型,这种数据类型感觉有点像指针,我们理解的时候可以理解为欸带起用来指向容器中某个元素. string,vector,[],很少用[],更常用的访问方式 ...
最新文章
- Centos下用lamp搭建日志服务器
- 前端框架Bootstrap 教程
- 机电传动控制第三次作业
- Python递归实现汉诺塔
- mysql数据表中取几列_MySQL实现表中取出随机数据
- linux ls命令shell脚本位置,linux - shell脚本到ls并在ls上执行命令结果 - SO中文参考 - www.soinside.com...
- 计算机408考研专业课思维导图(计算机组原理、数据结构、操作系统、计算机网络)
- (个人)AR电子书系统创新实训第三周(1)
- 华为手机使用应用沙盒动态修改imsi参数
- linux底层技术,Linux后端程序成长关键技术之底层体系结构
- str_rot13() 函数
- C语言中getch()的用法
- 她的话指引了很多人的未来生活———亦舒
- linux查看文件大小ls
- 关于MacPorts
- 海天蚝油《挑战不可能》实测5G超强传输能力
- 局域网 --- 共享文件夹设置与访问
- oracle网页客户端工具
- Allegro172版本DFM规则之DFA outline
- Python脚本运行出现语法错误