Rust的常规数组-Array数组(Array)在数据结构中是非常重要的概念,一般它具有以下几个特性: 数据元素必须是相
数组(Array)在数据结构中是非常重要的概念,一般它具有以下几个特性:
- 数据元素必须是相同的数据类型;
- 长度固定;
- 以下标0为访问起点;
- 在内存中占用一块连续的内存,元素在内存中是连续存储的;
- 访问元素速度快(时间复杂度为O(1)),但插入or删除速度慢(时间复杂度为O(n));
相信学过数据结构这门课程,亦或是拥有C/C++系语言编程经验的同学,都对上述内容很熟悉。
接下来我们来介绍一下Rust的数组(fixed-size array):
1. 数组的打印输出
fn main(){
let nums = [1,2,3,4,5];
// println!("{}",nums); // Error
println!("{:?}",nums);
println!("{:#?}",nums);
}
Error : E0277 doesn't implement std::fmt::Display
Note:in format strings you may be able to use {:?}
(or {:#?} for pretty-print) instead.(建议我们用{:?}
或者 {:#?}
替代)
2.数组的声明
当我们能用{:?}
或者 {:#?}
在控制台输出数组时,就可以看一下数组的声明。
2.1 声明方式一
fn main(){
let nums = [1,2,3,4,5]; // 等价于 let nums:[isize;5] = [1,2,3,4,5];
println!("{:?}",nums); // [1, 2, 3, 4, 5]
let sensons = ["Spring","Summer","Fall","Winter"]; // 等价于 let sensons:[&str;4] = ["Spring","Summer","Fall","Winter"];
println!("{:#?}",sensons);
}
[1, 2, 3, 4, 5]
[
"Spring",
"Summer",
"Fall",
"Winter",
]
采用这种方式声明数组,最好别轻易去加类型声明和数量,因为你会遇到各种令你抓狂的Panic。
- 你可能会出现声明的长度和初始化的长度没对应上.(help: consider specifying the actual array length)如:let nums:[isize;
6
] = [1,2,3,4,5];- 由于其他编程经验的影响,将String当作&str. 如:let sensons:[
String
;4] = ["Spring","Summer","Fall","Winter"];
所以非必要,可以尽情省去[类型;长度]
当你以为就这么简单的时候,可以试一下空数组
fn main(){
let empty = []; // -- type must be known at this point(此时需要知道类型)
}
error[E0282]: type annotations needed for
[_; 0]
很显然,空数组也需要知道其存储的类型 [_; 0]
,此处的_
可以具体类型来代替。
fn main(){
// let empty:[_;0] = []; // cannot infer type
let emtpy_arr_i32:[i32;0] = [];
println!("{:?}",emtpy_arr_i32); // []
let empty_arr_f64:[f64;0] = [];
println!("{:?}",empty_arr_f64); // []
let empty_arr_string:[String;0] = [];
println!("{:?}",empty_arr_string); // []
}
试想一下,此时让你给我声明一个100个初始值为0的数组,要是用第一种方式来写,那估计程序员要疯啊,下面就来看一下第二种声明方式。
2.2 声明方式二
这种声明方式在初始化数组时简单便捷。
fn main(){
// 声明方式二
let arr:[i32;5] = [0;5]; // 注意,我们可以加上数组的元素和长度说明。
println!("{:?}",arr); // [0, 0, 0, 0, 0]
let arr_str = ["W";5]; // ["W", "W", "W", "W", "W"]
println!("{:?}",arr_str);
// `_` can only be used on the left-hand side of an assignment
// `_` 只能被用在赋值表达式的左边
// let empty = [_;0];
let empty = [0;0]; // []
}
3.数组的操作
通常情况下,我们操作数组的方式为:(随机)访问、修改、遍历、插入、删除等。(因为这里讨论的是固定长度的数组,所以不涉及插入、删除操作)
3.1 数组的访问和遍历
数组访问永远绕不开的话题:Index out of bounds(数组越界),该错误在其他主流编程语言中一般都是运行时(Runtime) 才能被发现,但是Rust在编译期(Compile)就可以发现并指出该错误() 。
error: this operation will panic at runtime(该操作在runtime时会Panic)
另外Rust为我们提供了Iterator 和 Option可来提高程序的健壮性。
fn main(){
let nums = [1,2,3,4,5];
println!("{:?}",nums); // [1, 2, 3, 4, 5]
// (随机)访问
println!("{}",nums[3]); // 2
// error: this operation will panic at runtime
//println!("{}",nums[8]);// index out of bounds(数组越界)
// 访问数组的最后一个元素
println!("{}",nums.last()); Some(5)
println!("{:?}",nums[nums.len() - 1]); // 5
// 获取数组长度
println!("数组长度 = {:?}",nums.len()); // 5
println!("数组长度 = {:?}",nums.iter().count()); // 5
println!("数组长度 = {:?}",nums.iter().size_hint()); // (5, Some(5))
// 数组遍历(借助迭代器iter())
for x in nums.iter(){
println!("{}",x);
}
// 数组遍历(同时获取key,value)
for (index,element) in arr.iter_mut().enumerate(){
println!("index = {}, element = {}",index,element);
}
// 常用方式(但会 move ownership)
for x in nums {
println!("{}",x);
}
// 引用,不移动所有权
for x in &nums {
println!("{}",x);
}
}
3.2数组的修改
Rust的规则:Rust的变量默认时不可修改的
我们来尝试修改一下Rust的数组元素,(这里的修改only指的是修改数组指定下标上的元素。)
fn main(){
let arr = [0;5];
println!("{:?}",arr); // [0, 0, 0, 0, 0]
// 修改数组
arr[0] = 1; // cannot assign
}
error E0594: cannot assign to
arr[_]
, asarr
is not declared as mutable
help: consider changing this to be mutable(考虑将其变成可修改的)
fn main(){
let mut arr = [0;5];
println!("{:?}",arr);
arr[0] = 1;
arr[1] = 2;
arr[2] = 3;
arr[3] = 4;
arr[4] = 5;
println!("{:?}",arr);
}
在实际的编程过程中,上面的方式肯定是不可取的,我们基于当前的知识点来初始化数组。
fn main(){
let mut arr = [0;5];
println!("{:?}",arr); // [0, 0, 0, 0, 0]
// 传统方式
for i in 0..arr.len(){
arr[i] = (i+1) as i32;
}
println!("{:?}",arr); // [1, 2, 3, 4, 5]
// 借助于迭代器
for (index,element) in arr.iter_mut().enumerate(){
// (解引用 dereferencing)
*element = index + 1;
}
}
可以查看 enumerate()
在实际的开放过程中,Rust 提供了丰富的工具和方法来初始化和操作数组。
-
数组初始化的第三方库:array-init
-
数组初始化宏 std::array::from_fn
后续文章会带领大家揭开Rust迭代器的神秘面纱。
转载自:https://juejin.cn/post/7388908751259385891