数组

  • 数组是一种原生类型,可以在标准预制库中找到。
  • 由固定数量的相同类型的元素组成。
    数组的大小必须在编译时确定。在[]内指定数组的元素类型和数量,如
array_name[type: length]
[value1, value2, value3, ..., valueN]
[value; repeat];

例如

fn main() {
    let array_1: [i32; 3] = [1, 2, 3];
    let array_2 = [4, 5, 6];
    let array_3 = [7; 3];
    println!("{:?}",array_1);
    println!("{:?}",array_2);
    println!("{:?}",array_3);
}  

因为数组实现了Debug trait,因此我们可以通过{:?}占位符打印数组。

我们可以通过len方法输出数组的长度

fn main() {
   let array = [1,2,3,4,5,6,7];
   println!("{}", array.len());
}  

多维数组

一维数组只由列组成,二维数组是由行和列组成的,而三维数组是由行、列和深度组成的。维度的数量是没有限制的。
多维数组的声明语法如下(以三维举例):

[[[type; elements]; elements]; elements]

请添加图片描述

访问数组元素

数组下标从0开始的

fn main() {
    let array = [[[1,2,3,4],[5,6,7,8]],[[1,2,3,4],[5,6,7,8]],[[7,8,9,10],[9,10,11,12]]];
    println!("{}",array[0][1][2])
}

请添加图片描述

当我们尝试在数组中移动一个元素,这会导致数组的一部分内容不再被数组拥有,是不可预算的行为。因此是是不被允许的。

fn main() {
    let array = ["bob".to_string(), "alice".to_string()];
    let user = array[1];
}

修改方法就是使用借用

fn main() {
    let array = ["bob".to_string(), "alice".to_string()];
    let user = &array[1];
}

切片

一个切片是对数组一部分连续子元素构成的引用。语法如下

&arrayname[startIndex..endIndex]

示例

fn main() {
    let array = [1,2,3,4,5,6];
    println!("{:?}", &array[..4]);
    println!("{:?}", &array[1..]);
    println!("{:?}", &array[1..4]);
    println!("{:?}", &array[1..=4]);
}

数组的比较

数组只实现了用于比较的PartialEq trait,只能比较==或!=。
两个数组比较必须满足以下规则

  • 必须是相同类型元素。
  • 两个数组具有相同数量的元素
  • 数组里的元素类型本身必须实现 PartialEq,否则没法比较。
fn main() {
    let array_1 = [1,2,3,4];
    let array_2 = [1,2,3];
    let array_3 = [1,2,3,5];
    let array_4 = [1,2,3,4];

    println!("{}",array_1==array_3);
    println!("{}",array_1==array_4);
}

迭代

数组实现了IntoIterator trait,可以使用for-in迭代,for-in会自动调用数组的into_iter方法转换成迭代器。

fn main() {
    let array = [1, 2, 3, 4, 5, 6, 7, 8, 9];

    // 不包含索引
    for item in array {
        println!("{}",item);
    }
    // 包含索引
    for item in array.iter().enumerate() {
        println!("{:?}", item);
    }
}

隐式转换

有时我们需要将数组转换为切片,或者将切片转换为数组。在Rust中,从数组到切片是隐式的,而从切片转换到数组不是隐式的。
你可以在切片上调用try_into方法,这会返回一个Result<T, E>类型。如果成功,转换成的数组或包含在Ok()内,否则则返回一个Error<E>错误。
数组类型需要手动声明,并且声明数组类型需要与原切片的长度相同。

fn main() {
    let slice = &[1,2,3,4][1..3];
    let array:[i32; 2] = slice.try_into().unwrap();
    println!("{:?}", array);
}

向量

向量是动态数组,与数组不同的区别是,向量可以动态地伸长和收缩。

  • 由于向量的大小是动态的,它在编译时无法确定大小,因此向量本体不能驻留在栈上。
  • 向量有一个底层数组,元素值存储在其中。这个底层数组是在堆上分配的。
    向量有三个字段
  • 当前向量的大小
  • 指向堆区底层数组的指针
  • 底层数组的容量

这些字段不能直接访问,但可以通过调用方法进行访问。
向量创建时会分配底层数组,当向量的绑定从内存中移除时,底层数组也会被释放。
容量是向量当前的大小,长度是向量存储的实际元素的数量。
当长度超出容量时,底层数组会被重新分配、复制,并增加容量。

增加容量时,

  1. 分配了一个更大的底层数组,
  2. 所有值被复制到新的底层数组中
  3. 原来的底层数组被释放
  4. 更新向量的指针和容量。
    下图描述了一个常规向量的内存布局
    请添加图片描述

创建向量

通过new方法创建一个空向量

fn main() {
    let empty_vec = Vec::<i32>::new();
    println!("容量:{} 长度:{}", empty_vec.capacity(), empty_vec.len());
}

使用vec!初始化向量

fn main() {
    let vec = vec![1, 2, 3, 4];
    println!("{:?}",vec);
}

将数组转换为向量

let vec = [1,2,3,4].to_vec();

将切片转换为向量

fn main() {
    let splice = &[1,2,3,5];
    let vec = splice.to_vec();
    println!("{:?}", vec);
}

向量访问

对于向量的访问,使用get方法是更健全的方案。因为它返回的是一个Option枚举,如果成功,则返回Some<T>(其中T是索引对应的值),如果失败,则返回None

fn main() {
    let vec = vec![1,2,3,4];
    if let Some(val) = vec.get(5) {
        println!("{val}");
    } else {
        println!("索引值为空")
    }
}

迭代元素

你可以想遍历数组那样遍历向量。

fn main() {
    let vec = vec![1,2,3,4];
    for value in vec {
        println!("{value}");
    }
}

添加或移除元素

  • push() 将一个元素添加到vec末尾,没有返回值
  • pop() 移除最后一个元素并返回Option<T>,成功则将pop的值作为Some<T>返回,失败则返回None。
  • insert(index, value) 向任何位置(指定位置前面)插入元素,没有返回值。

容量

对于一个向量,容量是其底层数组的大小。当向量的大小要超出当前容量时,底层数组会被重新分配。合理地管理容量能够提高向量的性能。
常用管理容量的方法

  • with_capacity 用于设置初始容量
  • reserve 增加现有vec的容量
  • shrink_to_fit减小vec的容量来节约未使用的内存。
fn main() {
    let mut vec = Vec::with_capacity(5);
    vec.push(1);
    vec.push(3);
    vec.push(5);
    vec.push(7);
    vec.push(9);
    println!("当前容量:{} 元素个数: {}",vec.capacity(), vec.len());

    vec.reserve(8);
    println!("当前容量:{} 元素个数: {}",vec.capacity(), vec.len());

    vec.shrink_to_fit();
    println!("当前容量:{} 元素个数: {}",vec.capacity(), vec.len());
}
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐