Rust基础用法
数组操作
初始化数组
由于 Rust 数组是固定大小的栈上结构,不能"清空"长度,但可以重写所有元素。
推荐方式一:直接赋值新数组(最简洁高效)
rust
fn main() {
let mut arr: [u8; 4] = [1, 2, 3, 4];
println!("1:{:?}", arr); // 1:[1, 2, 3, 4]
// 复位为全 0
arr = [0; 4];
println!("2:{:?}", arr); // 2:[0, 0, 0, 0]
// 复位为全 false(bool 数组)
let mut flags: [bool; 4] = [true, false, true, false];
println!("3:{:?}", flags); // 3:[true, false, true, false]
flags = [false; 4];
println!("4:{:?}", flags); // 4:[false, false, false, false]
}
优点:
* 编译器会优化为 memset 或向量化指令
* 代码清晰、无 unsafe
* 适用于任何实现了 Copy 的类型(u8, i32, bool, f64 等)
推荐方式二:使用 fill() 方法(Rust 1.50+)
rust
fn main() {
let mut arr = [10u8, 20, 30, 40];
println!("初始化:{:?}",arr); // 初始化:[10, 20, 30, 40]
arr.fill(0); // 所有元素设为 0
println!("复位后:{:?}",arr); // 复位后:[0, 0, 0, 0]
let mut valid = [true, false, true];
println!("初始化:{:?}",valid); // 初始化:[true, false, true]
valid.fill(false);
println!("复位后:{:?}",valid); // 复位后:[false, false, false]
}
✅ 优点:
语义明确:"填充为某值"
适用于任何 Clone 类型(不仅限于 Copy)
比手动循环更安全高效
推荐方式三:使用 iter_mut().for_each()(灵活性高)
rust
fn main() {
let mut arr = [1, 2, 3, 4];
arr.iter_mut().for_each(|x| *x = 0);
// 或重置为不同逻辑(如递增)
arr.iter_mut().enumerate().for_each(|(i, x)| *x = i as u8);
}
仅在需要非统一值时使用,否则优先用 fill() 或直接赋值。
读/写数组
最佳实践:默认用 get / get_mut;仅在性能关键且逻辑确保安全时用直接索引或 unsafe。
| 操作 | 安全方法 | 返回类型 | 是否 panic |
|---|---|---|---|
| 读取 | .get(i) | Option<&T> | 否 |
| 写入 .get_mut(i) | Option<&mut T> | 否 | |
| 直接索引 | arr[i] / arr[i] = v | T / () | 是(越界时) |
| 极速访问 | get_unchecked(_mut) | &T / &mut T | 否(但 UB 风险) |
读取 → 用 get().and_then(...),安全且无 panic
写入 → 必须用 get_mut().and_then(...),并解引用赋值:*elem = value。
一维数组
在 Rust 中,一维数组(或切片、Vec)的安全读写是指:
读取 时不会因越界而 panic;
写入时既能避免越界,又能获得可变引用。
安全读取(只读)
方法:使用 .get(index)
rust
let arr = [10, 20, 30];
if let Some(&value) = arr.get(1) {
println!("arr[1] = {}", value); // 安全读取
}
// 若索引越界(如 arr.get(5)),返回 None,不会 panic
适用于:数组 [T; N],切片 &[T],Vec
返回类型是 Option<&T>,需用 match、if let 或 unwrap_or 等处理。
安全写入(修改)
方法:使用 .get_mut(index)
rust
let mut vec = vec![1, 2, 3];
if let Some(elem) = vec.get_mut(1) {
*elem = 99; // 安全修改
}
// vec 现在是 [1, 99, 3]
同样适用于:mut [T; N],&mut [T],Vec
返回 Option<&mut T>,解引用后即可赋值。
二维数组
固定大小多维数组
声明形如 [[T; COLS]; ROWS],访问、修改、遍历都用双重索引即可。
声明与初始化:let mut mat: [[i32; 4]; 3] = [[0; 4]; 3];
访问单个元素:let elem = mat[1][2];
修改单个元素:mat[0][0] = 1;
嵌套遍历:
rust
for row in &mat {
for &elem in row {
print!("{} ", elem);
}
println!();
}
越界访问会在运行时 panic,若需安全访问可用 get() 返回 Option:
安全取值(不 panic)
rust
if let Some(row) = mat.get(1) {
if let Some(&val) = row.get(2) {
println!("mat[1][2] = {}", val);
}
}
**对于固定大小数组 [[i32; N]; M]:**安全赋值
rust
if let Some(row) = mat.get_mut(i) {
if let Some(elem) = row.get_mut(j) {
*elem = 42;
}
}
注意:必须使用 get_mut() 才能获得 Option<&mut T>,然后通过 *elem = ... 赋值。
动态多维数组(Vec)
行、列可在运行时决定,访问方式与上面完全一样,只是创建方式不同:
声明:let mut mat = vec![vec![0; cols]; rows];
用法与上面完全一样:mat[i][j]、mat.get(i).and_then(|r| r.get(j)) 等。
rust
let mut mat = vec![vec![0; cols]; rows];
mat[0][0] = 1;
for row in &mat {
for &elem in row {
print!("{} ", elem);
}
println!();
}
正确的赋值方式:
rust
if let Some(row) = mat.get_mut(i) {
if let Some(elem) = row.get_mut(j) {
*elem = 42;
}
}
科学计算场景:ndarray
若做矩阵运算,可直接用 Array2:
rust
use ndarray::Array2;
let mut a = Array2::<usize>::zeros((2, 3));
a[[0, 1]] = 42; // 直接双索引
for row in a.rows() { // 按行迭代
println!("{:?}", row);
}
固定大小用 [[T; N]; M],动态用 Vec<Vec>,科学计算用 ndarray::Array2;访问语法都是 arr[i][j] 或 arr[[i, j]],配合 get() 可避免 panic。
三维数组
在 Rust 中安全地读写三维数组(无论是固定大小的 [[[T; N]; M]; P] 还是动态的 Vec<Vec<Vec>>),核心原则是:
逐层使用 .get() / .get_mut(),并通过 and_then 或嵌套 if let 安全解包,避免越界 panic。
固定大小三维数组(如 [[[i32; 4]; 3]; 2])
安全读取
rust
let arr: [[[i32; 4]; 3]; 2] = [[[0; 4]; 3]; 2];
// 方法一:链式 and_then
let value = arr.get(0)
.and_then(|patch| patch.get(1))
.and_then(|row| row.get(2));
match value {
Some(&v) => println!("arr[0][1][2] = {}", v),
None => println!("Index out of bounds"),
}
安全写入
rust
let mut arr: [[[i32; 4]; 3]; 2] = [[[0; 4]; 3]; 2];
// 使用 get_mut 链式
if let Some(plane) = arr.get_mut(0) {
if let Some(row) = plane.get_mut(1) {
if let Some(elem) = row.get_mut(2) {
*elem = 42;
}
}
}
// 注意:不能用 and_then 写入,因为 and_then 消费值,而我们需要可变引用链
动态三维数组(Vec<Vec<Vec>>)
创建
let mut arr = vec![vec![vec![0i32; 4]; 3]; 2]; // 2x3x4
安全读取(同上)
rust
let value = arr.get(0)
.and_then(|p| p.get(1))
.and_then(|r| r.get(2));
安全写入(嵌套 if let)
rust
if let Some(p) = arr.get_mut(0) {
if let Some(r) = p.get_mut(1) {
if let Some(e) = r.get_mut(2) {
*e = 100;
}
}
}
封装成通用函数(推荐)
为避免重复样板代码,可写辅助函数:
rust
fn safe_get_3d<T>(
arr: &[Vec<Vec<T>>],
p: usize, m: usize, n: usize) -> Option<&T> {
arr.get(p)?.get(m)?.get(n)
}
fn safe_set_3d<T>(
arr: &mut [Vec<Vec<T>>],
i: usize, j: usize, k: usize,
value: T) -> Result<(), ()> {
if let Some(p) = arr.get_mut(i) {
if let Some(r) = p.get_mut(j) {
if let Some(e) = r.get_mut(k) {
*e = value;
return Ok(());
}
}
}
Err(())
}
fn main() {
let mut arr = vec![vec![vec![0i32; 4]; 3]; 2];
let data = [[[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9,10,11,12]],
[[20,21,22,23],
[24,25,26,27],
[28,29,30,31]]];
for p in 0..2{
for m in 0..3{
println!("data[{}][{}]={:?}", p, m, data[p][m]);
for n in 0..4{
let _ = safe_set_3d(&mut arr, p, m, n, data[p][m][n]);
}
}
}
println!("arr={:?}", arr);
if let Some(v) = safe_get_3d(&mut arr, 0, 1, 2){
println!("v={}", v);
}
}
执行结果:
data[0][0]=[1, 2, 3, 4]
data[0][1]=[5, 6, 7, 8]
data[0][2]=[9, 10, 11, 12]
data[1][0]=[20, 21, 22, 23]
data[1][1]=[24, 25, 26, 27]
data[1][2]=[28, 29, 30, 31]
arr=[[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]], [[20, 21, 22, 23], [24, 25, 26, 27], [28, 29, 30, 31]]]
v=7