文章目录
Rust中
Vec
结构是对列表的实现,类比Java中的
ArrayList
。
不同于数组一旦创建其容量是固定不变的,列表的容量可以动态增加。
列表本身可以作为**栈(Stack)**来使用,Rust中列表可以直接调用
push()/pop()
在列表尾部增删元素。
创建列表
fn test03_list() {
// 空列表,初始容量为0
let mut list: Vec<i32> = Vec::new();
println!("capacity: {}", list.capacity());//0
// 首次添加元素,容量扩为4
list.push(1);
list.push(2);
list.push(3);
list.push(4);
println!("capacity: {}", list.capacity());//4
// 元素超出容量后,容量扩大一倍
list.push(5);
println!("capacity: {}", list.capacity());//8
println!("list[0]={}", list[0]);//1
println!("{:?}", list);//[1, 2]
// 加换行和缩进的“美化”打印
// [
// 1,
// 2,
// ]
println!("{:#?}", list);
// 创建一个带初始容量的列表
let list: Vec<i32> = std::vec::Vec::with_capacity(16);
println!("capacity: {}", list.capacity());//16
// 当然,更常用的是用vec!宏用来创建和初始化一个Vec
let digits: Vec<i32> = vec![0, 1, 2, 3, 4, 5];
// 创建一个初始值为0,长度为100的列表
let nums = vec![0; 100];
//nums: len=100, capacity=100
println!("nums: len={}, capacity={}", nums.len(), nums.capacity());
}
创建二维列表
// 创建3×2的二维列表
let p = vec![vec![0; 2]; 3];
let q = vec![vec![1,2], vec![3,4]];
列表切片
//列表切片
let digits = vec![0,1,2,3,4,5];
println!("{:?}", &digits[0..2]);//[0,1]
列表相等判断
两个列表可以通过==
/!=
符号直接判断是否相等。
也可以判断一个列表是否和另外一个列表的子列表是否相等。
let vec1 = vec![1, 2, 3];
let vec2 = vec![1, 2, 3, 4, 5];
// 判断列表和子列表是否相等
if vec1 == vec2[0..vec1.len()] {
println!("EQ!");
}
// 通过引用和切片判断是否相等
if &vec1 == &vec2[0..vec1.len()] {
println!("EQ!");
}
同理判断不相等:
let vec1 = vec![1, 2, 3];
let vec2 = vec![2, 2, 3, 4, 5];
if vec1 != vec2[0..vec1.len()] {
println!("NE!!");
}
if &vec1 != &vec2[0..vec1.len()] {
println!("NE!!");
}
列表当做栈(Stack)来使用
let mut list = vec![];
list.push(1);
list.push(2);
list.push(3);
assert_eq!(Some(3), list.pop());
遍历列表、求和
let digits = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
for i in 0..digits.len() {
println!("digits[{}]={}", i, digits[i]);
}
//求和
println!("sum={}", digits.iter().sum::<i32>());//45
println!("sum={}", digits.iter().fold(0, |x,a|x+a));//45
for (pos, v) in digits.iter().enumerate() {
println!("digits[{}]={}", pos, v);
}
// 让idx可修改,需要加mut(代表mutable)关键字
let mut idx = 0;
for x in digits.iter() {
println!("digits[{}]={}", idx, x);
// 和Python一样,rust不支持++和--
idx += 1;
}
let mut sum = 0;
for x in digits {
sum += x;
}
println!("sum={}", sum);//45
分组遍历
Rust的数组和列表上都实现了windows()
和chunks()
这2个方法。用于将数组/列表根据指定大小分组,分组的结果由一个切片迭代器(切片流)给出。
windows(size: usize)
滑动窗口归组。窗口大小固定为参数传入的size
。对迭代器进行遍历时,窗口每次往后滑动一个位置,生成下一个要访问的切片。
let arr = [1,2,3,4,5];//也可以是一个列表
// 闭包中的参数v是一个切片
// 输出:|1,2|2,3|3,4|4,5|
print!("|");
arr.windows(2).for_each(|v| {
print!("{},{}|", v[0], v[1]);
});
chunks(size: usize)
固定大小分组。对数组/列表中的数据按指定大小size
分块;最后一块/组中包含的数据量可能不足size。
let arr = vec![1,2,3,4,5];
// 闭包中的参数v是一个切片
// 输出:|1,2|3,4|5|
print!("|");
arr.chunks(2).for_each(|v| {
let s = v.iter().map(|x|x.to_string()).collect::<Vec<_>>().join(",");
print!("{s}|");
});
列表排序、二分查找
// 列表排序
let disorder = vec![3,-1,1,2,4,0];
// 从大到小排序,前面一小节讲述过闭包
let mut sorted1 = disorder.clone();
sorted1.sort_by(|x,y|y.cmp(x));
println!("{:?}", sorted1);
// 通过迭代器进行数据过滤和处理,然后collect()将Iter中的值收集到一个集合容器中
let some_data = vec![1,2,3,4,5,6];
let result_data: Vec<i32> = some_data.iter()
.filter(|&x|x%2==0)
.map(|x|x*x)
.collect();
println!("result_data: {:?}", result_data);//[4,16,36]
//Err(3)
println!("{:?}", found);
let last_elem: Option<&i32> = sorted1.last();
//Some(-1)
println!("{:?}", last_elem);