Rust之常用集合(一):向量(vector)

Rust学习教程32 - 动态数组Vec 本文节选自<<Rust语言圣经>>一书 欢迎大家加入Rust编程学院,一起学习交流: QQ群:1009730433 动态数组Vector 动态数组类型用Vec<T>表示,事实上,在之前的章节,它的身影多次出现,我们一直没有细讲,只是简单的把它当作数组处理。 动态数组允许你存储多个值,这些值在内存中一个紧挨着另一个排列,因此访问其中某个元素的成本非常低。动态数组只能存储相同类型的元素,如果你想存储不同类型的元素,可以使用之前讲过的枚举类型或者特征对象. 总之,当我们想拥. 阅读详情

开发环境

  • Windows 10
  • Rust 1.64.0

 

  •   VS Code 1.72.2 

项目工程

这里继续沿用上次工程rust-demo

常用集合

Rust的标准库包括许多非常有用的数据结构,称为集合。大多数其他数据类型表示一个特定的值,但是集合可以包含多个值。与内置数组和元组类型不同,这些集合指向的数据存储在堆上,这意味着数据量在编译时不需要知道,并且可以随着程序运行而增长或收缩。每一种收藏都有不同的功能和成本,选择一种适合你当前情况的收藏是一项你需要慢慢培养的技能。我们将讨论Rust程序中经常使用的三个集合:

  • vector允许你存储可变数量的相邻值。
  • string是字符的集合。
  • hash map允许您将一个值与一个特定的键相关联。这是一个更一般的数据结构的特殊实现,称为map。

用向量存储值列表

我们要看的第一个集合类型是Vec<T >,也称为vector。向量允许您在一个数据结构中存储多个值,该数据结构将所有值在内存中相邻放置。向量只能存储相同类型的值。当您有一个项目列表时,例如文件中的文本行或购物车中的项目价格时,它们非常有用。

创建向量

为了创建一个新的空向量,我们调用Vec::new函数

fn main() {
    let v: Vec<i32> = Vec::new();       // 创建vector
}

注意,我们在这里添加了一个类型注释。因为我们没有在这个向量中插入任何值,所以Rust不知道我们打算存储什么样的元素。这是很重要的一点。向量是使用泛型实现的;现在,我们知道标准库提供的Vec<T >类型可以保存任何类型。当我们创建一个向量来保存一个特定的类型时,我们可以在尖括号中指定类型。在上例中,我们已经告诉Rust,v中的Vec<T >将保存i32类型的元素。

更常见的是,您将创建一个带有初始值的Vec < T >, Rust将推断出您想要存储的值的类型,因此您很少需要做这种类型注释。Rust方便地提供了vec!宏,它将创建一个新的向量来保存您给它的值。下例中创建了一个新的Vec<i32 >,它包含值1、2和3。整数类型是i32,因为这是默认的整数类型,

fn main() {
    let v = vec![1, 2, 3];           // 带有初始值的vector
}

因为我们已经给出了初始i32值,Rust可以推断出v的类型是Vec<i32 >,类型注释是不必要的。接下来,我们将看看如何修改向量。

更新向量

要创建一个向量,然后向其中添加元素,我们可以使用push方法,

fn main() {
    let mut v = Vec::new();         // mut关键字,创建可修改的向量vector

    v.push(5);                      // 和其他语言类似,传入数据
    v.push(6);
    v.push(7);
    v.push(8);
}

和任何变量一样,如果我们希望能够改变它的值,我们需要使用mut关键字使它可变,如第3章所讨论的。我们放入的数字都是i32类型的,Rust从数据中推断出这一点,所以我们不需要Vec<i32 >注释。

读取向量的元素

有两种方法可以引用存储在vector中的值:通过索引或者使用get方法。在下面的例子中,为了更加清晰起见,我们对这些函数返回的值的类型进行了注释。

fn main() {
    let v = vec![1, 2, 3, 4, 5];                // 定义向量

    let third: &i32 = &v[2];                     // 通过索引获取向量中的值
    println!("The third element is {}", third);

    let third: Option<&i32> = v.get(2);          // 通过get接口获取向量中的值
    match third {
        Some(third) => println!("The third element is {}", third),
        None => println!("There is no third element."),
    }
}

编译运行

cargo run

  结果

 请注意这里的一些细节。我们使用索引值2来获取第三个元素,因为向量是由数字索引的,从零开始。使用&和[]给出了对索引值处元素的引用。当我们使用get方法并将索引作为参数传递时,我们得到一个可以与match一起使用的Option< &T>。

Rust提供这两种方法引用元素的原因是,当您试图使用现有元素范围之外的索引值时,您可以选择程序的行为方式。作为一个例子,让我们看看当我们有一个包含五个元素的向量,然后我们尝试用每种技术访问索引为100的元素时会发生什么,

fn main() {
    let v = vec![1, 2, 3, 4, 5];

    let does_not_exist = &v[100];         // 获取索引为100的值
    let does_not_exist = v.get(100);
}

 编译运行

cargo run

 当我们运行这段代码时,第一个[]方法将导致程序崩溃,因为它引用了一个不存在的元素。如果试图访问超过vector末尾的元素,希望程序崩溃时,最好使用这种方法。

当get方法被传递一个在vector之外的索引时,它返回None而不会死机。如果在正常情况下偶尔会访问vector范围之外的元素,那么可以使用这个方法。然后你的代码将有逻辑来处理有Some(&element)或者None,如之前章节讨论的。例如,索引可能来自输入数字的人。如果他们不小心输入了一个太大的数字,程序得到一个None值,你可以告诉用户当前向量中有多少项,然后再给他们一次输入有效值的机会。这比因为一个打字错误而导致程序崩溃更容易操作!

当程序有一个有效的引用时,借用检查器执行所有权和借用规则以确保这个引用和任何其他对vector内容的引用保持有效。回想一下在同一个作用域中不能有可变和不可变引用的规则。这条规则适用于下例,我们保存了一个对向量中第一个元素的不可变引用,并试图在末尾添加一个元素。如果我们试图在函数的后面引用这个元素,这个程序将无法运行:

fn main() {
    let mut v = vec![1, 2, 3, 4, 5];          // 可变的向量

    let first = &v[0];

    v.push(6);                                // 改变值

    println!("The first element is: {}", first);
}

编译运行

cargo run

编译错误 

 上例中的代码看起来应该是可行的:为什么对第一个元素的引用要关心向量末尾的变化?这个错误是由vector的工作方式造成的:因为vector将值彼此相邻地放在内存中,所以在vector的末尾添加新元素可能需要分配新的内存,并将旧的元素复制到新的空间,如果没有足够的空间将所有元素彼此相邻地放在vector当前存储的位置。在这种情况下,对第一个元素的引用将指向已释放的内存。借用规则防止程序在这种情况下终止。

迭代向量中的值

为了依次访问vector中的每个元素,我们将遍历所有元素,而不是使用索引一次访问一个元素。下例中显示了如何使用一个for循环来获得对i32值的向量中的每个元素的不可变引用,并打印它们。

fn main() {
    let v = vec![100, 32, 57];
    for i in &v {                     // for循环
        println!("{}", i);
    }
}

编译运行

cargo run

 我们还可以迭代可变向量中每个元素的可变引用,以便对所有元素进行更改。下例中中的for循环将每个元素加50。

fn main() {
    let mut v = vec![100, 32, 57];
    for i in &mut v {
        *i += 50;              // 每个数加 50
        println!("{}", i);
    }
}

编译运行

cargo run

 

 要改变可变引用所引用的值,我们必须在使用+=操作符之前使用* 接触引用操作符来获得I中的值。

由于借用检查器的规则,迭代一个向量,无论是不变的还是可变的,都是安全的。如果我们试图在上例中的for循环体中插入或删除项目,我们会得到一个类似于上述其中代码的编译错误。对for循环持有的向量的引用防止了对整个向量的同时修改。

使用枚举存储多种类型

向量只能存储相同类型的值。这可能不方便;肯定有需要存储不同类型的项目列表的用例。幸运的是,一个枚举的变体是在同一个枚举类型下定义的,所以当我们需要一个类型来表示不同类型的元素时,我们可以定义并使用一个枚举!

例如,假设我们想从电子表格的一行中获取值,该行中的一些列包含整数、一些浮点数和一些字符串。我们可以定义一个枚举,它的变量包含不同的值类型,所有的枚举变量都被认为是相同的类型:枚举的类型。然后我们可以创建一个向量来保存这个枚举,最终保存不同的类型。

fn main() {
    enum SpreadsheetCell {          // 枚举
        Int(i32),
        Float(f64),
        Text(String),
    }

    let row = vec![                           // 将枚举类型存入向量
        SpreadsheetCell::Int(3),
        SpreadsheetCell::Text(String::from("blue")),
        SpreadsheetCell::Float(10.12),
    ];
}

Rust需要知道在编译时vector中有哪些类型,这样它就能准确地知道在堆中需要多少内存来存储每个元素。我们还必须明确在这个向量中允许什么类型。如果Rust允许vector保存任何类型,那么有可能一个或多个类型会导致对vector元素执行的操作出错。使用枚举加match表达式意味着Rust将确保在编译时处理每一种可能的情况。

如果你不知道一个程序在运行时将在vector中存储的所有类型,enum技术就不起作用。

既然我们已经讨论了使用vectors的一些最常见的方法,可以查看Rust API文档,了解标准库在Vec<T >上定义的许多有用的方法。例如,除了push之外,pop方法还移除并返回最后一个元素。

删除向量会删除其元素

像任何其他struct一样,向量在超出范围时被释放,

fn main() {
    {
        let v = vec![1, 2, 3, 4];

        // do stuff with v
    } // <- v goes out of scope and is freed here         // 有效范围
}

当vector被丢弃时,它的所有内容也被丢弃,这意味着它保存的整数将被清除。借用检查器确保仅当向量本身有效时,才使用对向量内容的任何引用。

本章重点

  • 向量vector概念及创建方法
  • 向量的使用 - 更新数据
  • 读取向量中的元素
  • 迭代向量中的值
  • 使用枚举存储多类型的数据

17-5 向量数据库之野望5 - 使用 Rust 实现矢量数据库 矢量数据库是一种针对存储和查询矢量(表示高维空间中的点的数字数组)进行了优化的数据库。这些数据库对于在大型数据集中进行相似性搜索是关键操作的应用至关重要,例如推荐系统、图像检索和自然语言处理。矢量数据库中的关键概念包括:这些数据库中的向量表示数据点。例如,在图像识别中,图像可能表示为高维向量,其中每个维度对应于图像的一个特征。为了检索相似的向量,数据库需要一种方法来量化两个向量的“接近”或“相似”程度。常用度量包括欧几里得距离、曼哈顿距离和余弦相似度。在高维空间中进行高效搜索是一个具有挑战性的问题。 阅读详情

相关推荐

【Rust通用集合类型】Rust向量Vector、String、HashMap原理解析与应用实战

Rust 标准库中包含一系列被称为 集合(collections)的非常有用的数据结构。 大部分其他数据类型都代表一个特定的值,不过集合可以包含多个值。 不同于内建的数组和元组类型,这些集合指向的数据是储存在堆上的,这意味着数据的数量不必在编译时就已知并且可以随着程序的运行增长或缩小。 每种集合都有着不同能力和代价,而为所处的场景选择合适的集合则是你将要始终成长的技能。 在这一章里,我们将详细的了解三个在 Rust 程序中被广泛使用的集合: vector,String,HashMap。

景天科技苑 7万+

Rust 动态数组Vec基本概念及其用法

Rust中的Vec是一种动态数组,它可以在运行时自动调整大小。Vec是Rust标准库的一部分,提供了一种高效、安全的方式来处理大量数据。基于堆内存申请的连续动态数据类型,其索引、压入(push)、弹出(pop) 操作的时间复杂度为 O(1)。

汉阳Hann's Home 1万+

Rust语言入门教程(十一) - 集合类型Collections

在 Rust 中,collections 是一组用于存储多个值的标准库数据结构。不同于数组和元组,collections 可以存储可变数量的数据。Rust 的标准库提供了几种常用的集合类型,每种类型都有其特定的用途和性能特点。

因吹斯汀 511

Rust 动态数组Vector

哪怕只是拿了某个元素的可变引用,也不能再获得Vector整体的不可变引用。表示,可以看成java的集合吧,和Golang的切片还是有点区别。v.get(2) 也是访问第三个元素,但是有所不同的是,它返回了。从安全性出发,get更安全,get在内部做了处理,,因此 v.get 的使用方式非常安全。,如果不想自己写,可以使用派生的比较特征。其实如果你想放不同类型的数据,可以考虑。如果是特征对象,得保证不同类型都。动态数组允许你存储多个值,分为下标访问和get访问。,访问效率高,但是只能。

vince1998的博客 1301

告别混乱接线!用EPLAN 3D布局图,手把手教你搞定电气柜的3D建模与自动布线

本文详细介绍了如何使用EPLAN 3D布局图进行电气柜的3D建模与自动布线,帮助工程师告别混乱接线。从项目准备、基础结构建模到智能设备布局与逻辑定义,再到高级布线技术与问题排查,提供了一套完整的实战指南。通过EPLAN的3D功能,显著提升设计效率与系统可靠性。

weixin_30680385的博客 339

Redis【实战篇】---- 分布式锁-redission

重入问题:重入问题是指 获得锁的线程可以再次进入到相同的锁的代码块中,可重入锁的意义在于防止死锁,比如HashTable这样的代码中,他的方法都是使用synchronized修饰的,假如他在一个方法内,调用另一个方法,那么此时如果是不可重入的,不就死锁了吗?所以可重入锁他的主要意义是防止死锁,我们的synchronized和Lock锁都是可重入的。不可重试:是指目前的分布式只能尝试一次,我们认为合理的情况是:当线程在获得锁失败后,他应该能再次尝试获得锁。

是微风,是晚霞,是无可替代 1万+

【Rust 基础篇】Rust Vector(向量)详解

在 Rust 中,可以使用Vec<T>来定义和创建一个 Vector,其中的T是 Vector 存储的元素类型。在上述示例中,我们创建了一个空的整数类型的 Vector,使用Vec::new()方法来初始化。另一种创建 Vector 的方式是使用宏vec!在上面的示例中,我们使用vec!宏创建了一个包含 1 到 5 的整数的 Vector。本篇博客介绍了 Rust 中的 Vector 类型,包括定义、创建、常用方法和使用示例。

繁依Fanyi的博客 1941

CH582低功耗实战:从1.2mA降到5uA,我的蓝牙广播功耗优化笔记

本文详细记录了沁恒CH582蓝牙芯片从1.2mA降至5μA的功耗优化全过程。通过建立基准测试环境、分层排查软件配置与IO状态、精细调优射频参数以及硬件层面的电源管理,实现了极致的低功耗表现。文章还提供了实用的功耗测量方法和典型问题排查指南,为蓝牙设备开发者提供了宝贵的参考经验。

weixin_30368405的博客 572

Rust 集合类型之Vector 向量

宏,这个宏根据我们提供的值来创建一个新的vector。在rust语言中,Vector(向量)是一种动态数组,可以存储相同类型的元素。但是有时我们需要储存一系列不同类型的值的时候,使用枚举以便在vector中存放不同类型的数据。为了修改可变引用所指向的值,在使用 += 运算符之前必须使用解引用运算符(*)获取 i 的值。我们也可以遍历可变vector的每一个元素的可变引用以便能改变它们。Vector是标准库的一种集合类型,通过使用Vec<T>来声明。向新建的vector增加元素,可以使用push方法。

qq5551230的博客 866

Arcgis使用NDVI值遥感反演叶面积指数(LAI)

经验模型反演操作不难,主要是要多看文献,了解公式。本文中的公式我也不清楚是哪个作物的NDVI和LAI的关系(别人提供的),继续看文献整理吧。后续会在下面罗列更新一下主要公式。

所有专家都曾始于新手 8430

YOLO26轻量化科研实践:PartialConv驱动CSPCPC模块,让模型参数量直降1000W且精度不减

在目录下,新建AddModules文件夹,将cspcpc.py放入其中。

m0_71589036的博客 166

【Rust自学】8.1. Vector

Vector由标准库提供,在Vector里可以存储多个值,而且这些值的类型是相同的,它们在内存中是连续存放的。可以把它视为可以扩展的数组。

A Rookie in San Domenico School 1367

RK AVS双目融合记录

NOTE] 调试平台双目avs融合调试,需要先保证两个摄像头能正常出图同时出流。使用默认工具测试vi->avs->venc通路是否正常,-a可指定isp效果文件需要开启CONFIG_VIDEO_ROCKCHIP_AVSP和CONFIG_VIDEO_ROCKCHIP_FEC,dts中使能。

mangofu的博客 104

Rust 常用集合(上)

在开始深入这些方面之前,我们需要讨论一下术语字符串的具体意义。Rust 的核心语言中只有一种字符串类型:字符串 slicestr,它通常以被借用的形式出现,&str。第四章讲到了字符串 slices:它们是一些对储存在别处的 UTF-8 编码字符串数据的引用。举例来说,由于字符串字面值被储存在程序的二进制输出中,因此字符串字面值也是字符串 slices。字符串(String)类型由 Rust 标准库提供,而不是编入核心语言,它是一种可增长、可变、可拥有、UTF-8 编码的字符串类型。

专注于大数据方向,区块链,前后端,数据可视化,人工智能等领域 2101

[Dify] -进阶13- 使用“知识库 + 工作流”打造智能推荐系统

本文介绍了在Dify平台上构建智能推荐系统的方法,重点阐述了知识库与工作流技术的结合应用。通过知识库管理RAG流程,实现文档上传、向量嵌入和检索优化;利用工作流设计节点化推荐逻辑,支持并行处理与条件分支。以电话销售话术推荐为例,展示了从数据收集到实时生成的完整流程。该方法具有准确性高、扩展性强、维护简便等优势,可广泛应用于各类推荐场景,实现从数据存储到智能推荐的闭环解决方案。

技术小甜甜:传播可落地技术,帮助个人和企业降低解决真实场景问题的成本 1067

通过情感分类实例 详细介绍如果借助Huggingface平台 完成Transformers模型运行(包括配置环境-tokenizer-Model-输出头-预测)

attention_mask和padding是配套使用的,当人为去修改padding的时候,也要把attention_mask里面的参数进行修改。下载Huggingface包,Huggingface可以说是一个社区,集成了很多nlp的模型、数据集、预训练权重文件等等,并且免费,只需要pip install下载即可。那么用什么做分类就选择什么输出头,就import什么东西。代码中使用了自动分词器选择,它是由checkpoint指定的预训练模型关联的,不用我们自己选择tokenizer,它自动帮我们选择好了。

LZL2020LZL的博客 1135

30天拿下Rust之向量

在Rust语言中,向量(Vector)是一种动态数组类型,可以存储相同类型的元素,并且可以在运行时改变大小。向量是Rust标准库中的一部分,位于std::vec模块中。向量是一个非常灵活和强大的数据结构,可以方便地用于各种场景,包括:存储数据、处理集合、构建动态数组等。

hope_wisdom的技术博客 1780

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

【Rust编程:从小白入坑】Rust集合类型 - Vector详解

本文全面介绍了Rust中Vector(可变长度数组)的基本操作和高级用法。主要内容包括:Vector的创建(3种方式)、元素添加/访问/修改/删除操作、遍历方法(3种方式)、长度容量属性管理、常用方法(查找、排序、去重)、切片操作以及高级功能(映射、过滤)。文章通过大量代码示例展示了Vector的安全访问机制(get方法避免panic)、内存管理优化(容量预留)和函数式编程特性(map/filter等),帮助开发者深入理解并高效使用这一核心集合类型。

小淼淼的博客 410

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

《Rust语言圣经》Rust教程笔记25:2.Rust基础入门(2.9集合类型)2.9.1Rust动态数组、Rust Vector(同质容器、非稳定排序、浮点数数组排序、结构体数组排序)

Rust 的Vec设计为只能存储同一种类型的元素,以保证类型安全、内存效率和性能。如果需要存储多种类型的元素,可以使用enum或等方法来间接实现这一功能。从上面我们学习过程当中,排序需要我们实现Ord特性,那么如果我们把我们的结构体实现了该特性,是否就不需要我们自定义对比函数了呢?是,但不完全是,实现Ord需要我们实现OrdEqPartialEqPartialOrd这些属性。好消息是,你可以deriveage: u32,println!("{:?执行输出需要deriveOrd。

Dontla的博客 1551

【Rust】数组与向量:集合类型全解

/ 显式类型// 类型推断10];// 重复初始化// 定义通用集合操作self.pop()总结对比维度数组向量定义[T;N]Vec<T>大小固定(编译时)动态(运行时)内存通常栈上堆上性能极快(无分配)快(有分配)灵活性低高适用常量数据、缓冲区动态集合、未知大小关键决策点数据量小且固定→ 数组数据量未知或可变→ 向量性能敏感→ 优先数组,次选预分配向量代码通用→ 使用切片特质&[T]两者结合使用,数组处理固定模式,向量处理动态数据,通过特质提供统一接口。

weixin_43219667的博客 577

08-常用集合(容器)

我们首先定义一下字符串的含义。Rust 的核心语言中只有一种字符串类型,那就是字符串片str,它的借用形式通常是&str。在第 4 章中,我们谈到了字符串片,它是对存储在其他地方的UTF-8 编码字符串数据的引用。例如,字符串字面量存储在程序的二进制文件中,因此是字符串片。String 类型是由 Rust 标准库提供的,而不是编入核心语言的,它是一种可增长、可变、自有、UTF-8 编码的字符串类型。

优快云爱好者的独到见解 1411

【Rust】集合的使用——Rust语言基础16

看过上一篇博客的长篇大论一定很疲惫,不过笔者保证这一篇我们将会很轻松的度过~在其它编程语言中也会有集合这样的类似概念,例如在C++中将这种数据结构称为容器,而在Rust中则将这些数据结构称为集合集合是一种非常有用的数据结构,当有一类具有相同属性或者共同点的东西归类或统计时,集合就会派上大用处。在Rustvector:存储一系列同类型数量可变的值;字符串(string):这时字符的集合,本文将会着重介绍它;哈希 map(hash map):每个成员是由一个唯一存在的关键字(key。

Imagine Miracle的博客 1233

Rust 集合与字符串

Rust 集合与字符串 集合(Collection)是数据结构中最普遍的数据存放形式,Rust 标准库中提供了丰富的集合类型帮助开发者处理数据结构的操作。 向量 向量(Vector)是一个存放多值的单数据结构,该结构将相同类型的值线性的存放在内存中。 向量是线性表,在 Rust 中的表示是 Vec<T>。 向量的使用方式类似于列表(List),我们可以通过这种方式创建指定类型的向量: let vector: Vec<i32> = Vec::new(); // 创建类型为 i32 的空

神棍之路 844

rust容器

标准库提供了常见的容器。包括向量 ( Vector )、映射( HashMap )、集合( HashSet )。

void的博客 927
上一篇: Rust之包,箱和模块管理(五):将模块分成不同的文件
下一篇: Rust之常用集合(二):字符串(String)
枫★曦
博客等级 码龄19年 251粉丝 153原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值