当前位置: 首页 > news >正文

Rust数组与向量

数组

  • 数组是一种原生类型,可以在标准预制库中找到。
  • 由固定数量的相同类型的元素组成。
    数组的大小必须在编译时确定。在[]内指定数组的元素类型和数量,如
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());
}
http://www.dtcms.com/a/403592.html

相关文章:

  • 【LeetCode 每日一题】1886. 判断矩阵经轮转后是否一致
  • linux下进程coredump分析
  • 【数据结构学习篇】--栈和stack
  • 钻研视频——破细节
  • 网站建设哪家某网站项目策划书
  • 网站建设制作设计公司佛山内蒙网站建设赫伟创意星空科技
  • 上海网站seo策划设计工具
  • 声明式事务6
  • 南京建设网站公司做车品的网站
  • Next.js动态路由介绍([projectId]/page.tsx:动态路由参数、参数占位符、动态参数、动态数据)无需预创建目录、共享页面逻辑
  • Java核心之泛型
  • 直播进入“智”时代!智享 AI 驱动个性化内容,升级高效互动场景
  • 河南襄县做网站的公司查企业官网
  • Linux:fork()函数详解:原理、用法及经典面试题解析
  • tensorflow卷积层1——卷积和池化
  • tensorflow加载和预处理数据
  • DAY 03 CSS的认识
  • 黑群晖做php网站pc网站手机网站
  • Jakarta EE 实验 — Web 聊天室(过滤器、监听器版)
  • 做js题目的网站知乎抖音代运营公司合法吗
  • MyBatis的最佳搭档(MyBatis-Plus)
  • 无用知识研究:和普通函数不同,返回类型也参与了模板函数的signature
  • 简单小结类与对象
  • Java 大视界 -- Java 大数据机器学习模型在金融风险传染路径分析与防控策略制定中的应用
  • 【C++】Template:深入理解特化与分离编译,破解编译难题
  • 【把15v方波转为±7.5v的方波】2022-12-21
  • 自己可以做一个网站吗自己怎么做直播网站吗
  • 嵌入式开发常见问题解决:Keil头文件路径与MCUXpresso外设配置错误
  • 从Android到iOS:启动监控实现的跨平台技术对比
  • 数据开放网站建设内容大连可以做网站的公司