存储过程能用if not exist_Rust用vector存储数据

16a9017b045be70d2d12f3aa55e41416.png

我们将要研究的第一个集合类型是矢量Vec,也称为矢量。向量使您可以在单个数据结构中存储多个值,该结构将所有值彼此相邻放置在内存中。向量只能存储相同类型的值。当您具有项目列表时,例如文件中的文本行或购物车中项目的价格时,它们很有用。

创建一个新的向量

要创建一个新的空向量,我们可以调用该Vec::new函数,如清单8-1所示。

    let v: Vec = Vec::new();

清单8-1:创建一个新的空向量来保存类型的值 i32

请注意,我们在此处添加了类型注释。因为我们没有在此向量中插入任何值,所以Rust不知道我们打算存储哪种元素。这是重要的一点。向量是使用泛型实现的;我们将在第10章中介绍如何将泛型与您自己的类型一起使用。现在,您知道Vec标准库提供的类型可以容纳任何类型,并且当特定向量具有特定类型时,该类型将在尖括号中指定。在清单8-1中,我们告诉Rust,Vecinv将容纳该i32类型的元素。

在更实际的代码中,Rust通常可以在插入值后就推断出要存储的值的类型,因此您几乎不需要执行此类型注释。创建Vec具有初始值的更为常见,Rustvec!为方便起见提供了该宏。宏将创建一个新向量,其中包含您提供的值。清单8-2创建一个新的Vec保存价值1,2和3。整数类型是i32因为这是默认的整数类型,正如我们在第3章的“数据类型”一节中讨论的那样。

    let v = vec![1, 2, 3];

清单8-2:创建一个包含值的新向量

因为我们已经给定了初始i32值,所以Rust可以推断出的类型v 为Vec,并且不需要类型注释。接下来,我们将研究如何修改向量。

更新向量

要创建一个向量,然后向其中添加元素,我们可以使用push方法,如清单8-3所示。

    let mut v = Vec::new();    v.push(5);    v.push(6);    v.push(7);    v.push(8);

清单8-3:使用该push方法向向量添加值

与任何变量一样,如果我们希望能够更改其值,则需要使用mut关键字使它可变,如第3章中所述。我们放入其中的数字均为type i32,Rust从数据中推断出这一点,因此我们不需要Vec注释。

删除向量将删除其元素

像其他任何struct一个向量一样,向量超出范围时将被释放,如清单8-4所示。

    {        let v = vec![1, 2, 3, 4];        // do stuff with v    } // 

清单8-4:显示放置向量及其元素的位置

删除向量时,其所有内容也将被删除,这意味着将清除其拥有的那些整数。这似乎很简单,但是当您开始引入对向量元素的引用时,可能会变得更加复杂。让我们接下来解决这个问题!

向量的阅读要素

既然您知道如何创建,更新和销毁向量,那么下一步就是了解如何读取向量的内容。有两种方法可以引用存储在向量中的值。在示例中,我们为从这些函数返回的值的类型添加了注释,以更加明确。

清单8-5展示了两种使用索引语法或方法访问向量中值的get方法。

    let v = vec![1, 2, 3, 4, 5];    let third: &i32 = &v[2];    println!("The third element is {}", third);    match v.get(2) {        Some(third) => println!("The third element is {}", third),        None => println!("There is no third element."),    }

清单8-5:使用索引语法或get方法访问向量中的项目

请在此处注意两个细节。首先,我们使用的索引值2获取第三个元素:向量从零开始按数字索引。其次,获得第三个元素的两种方法是使用&和[],这为我们提供了一个参考,或者使用get将索引作为参数传递的方法,这给了我们一个Option。

Rust有两种引用元素的方式,因此您可以选择在尝试使用向量没有元素的索引值时程序的行为。作为一个示例,让我们看看如果程序具有一个包含五个元素的向量,然后尝试访问索引为100的元素,该程序将如何执行,如清单8-6所示。

    let v = vec![1, 2, 3, 4, 5];    let does_not_exist = &v[100];    let does_not_exist = v.get(100);

清单8-6:尝试在包含五个元素的向量中访问索引为100的元素

当我们运行此代码时,第[]一种方法将导致程序出现恐慌,因为它引用了不存在的元素。如果要访问向量结尾之后的元素,则当您希望程序崩溃时,最好使用此方法。

当该get方法传递给向量之外的索引时,它None不会惊慌地返回 。如果在正常情况下偶尔访问超出向量范围的元素,则可以使用此方法。然后,您的代码将具有处理或包含Some(&element)或的 逻辑None,如第6章中所述。例如,索引可能来自输入数字的人。如果他们不小心输入了一个太大的数字,并且程序获得了一个None值,则可以告诉用户当前向量中有多少个项目,并给他们另一个输入有效值的机会。这比由于错字而导致程序崩溃更人性化!

当程序具有有效的引用时,借位检查器将执行所有权和借用规则(在第4章中介绍),以确保该引用和对向量内容的任何其他引用保持有效。回想一下规则,该规则规定在同一范围内不能有可变和不可变的引用。该规则适用于清单8-7,其中我们对向量中的第一个元素持有不可变的引用,并尝试将元素添加到末尾,如果我们稍后还要在函数中引用该元素,则该规则将不起作用:

    let mut v = vec![1, 2, 3, 4, 5];    let first = &v[0];    v.push(6);    println!("The first element is: {}", first);

清单8-7:尝试在保留对项目的引用的同时向矢量添加元素

编译此代码将导致以下错误:

$ cargo run   Compiling collections v0.1.0 (file:///projects/collections)error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable --> src/main.rs:6:5  |4 |     let first = &v[0];  |                  - immutable borrow occurs here5 | 6 |     v.push(6);  |     ^^^^^^^^^ mutable borrow occurs here7 | 8 |     println!("The first element is: {}", first);  |                                          ----- immutable borrow later used hereerror: aborting due to previous errorFor more information about this error, try `rustc --explain E0502`.error: could not compile `collections`.To learn more, run the command again with --verbose.

清单8-7中的代码可能看起来应该工作:为什么对第一个元素的引用应该关心向量结尾处的变化?此错误是由于向量的工作方式造成的:如果没有足够的空间将所有元素放在每个元素的旁边,则在向量的末尾添加新元素可能需要分配新的内存并将旧元素复制到新空间向量当前所在的其他位置。在这种情况下,对第一个元素的引用将指向释放的内存。借用规则阻止程序在这种情况下结束。

注意:有关该Vec类型的实现细节的更多信息,请参见“ The Rustonomicon”。

遍历向量中的值

如果我们想依次访问向量中的每个元素,则可以遍历所有元素,而不必一次使用索引来访问一个。清单8-8显示了如何使用for循环获取i32值向量中每个元素的不可变引用并进行打印。

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

清单8-8:通过使用for循环遍历元素来打印向量中的每个元素

我们还可以迭代对可变向量中每个元素的可变引用,以对所有元素进行更改。for清单8-9中的循环将添加50到每个元素。

    let mut v = vec![100, 32, 57];    for i in &mut v {        *i += 50;    }

清单8-9:迭代对向量中元素的可变引用

要更改可变引用所引用的值,我们必须使用解引用运算符(*)来获取值,i然后才能使用该 +=运算符。我们将在 第15章的“使用Dereference运算符跟随指针到值”部分中进一步讨论dereference运算符 。

使用枚举存储多种类型

在本章开始时,我们说过向量只能存储相同类型的值。这可能会带来不便;肯定有一些用例需要存储不同类型的项目列表。幸运的是,枚举的变体是在相同的枚举类型下定义的,因此当我们需要在向量中存储不同类型的元素时,我们可以定义和使用枚举!

例如,假设我们要从电子表格的一行中获取值,其中该行中的某些列包含整数,一些浮点数和一些字符串。我们可以定义一个枚举,其变量将包含不同的值类型,然后所有枚举变量将被视为相同的类型:枚举的类型。然后,我们可以创建一个包含该枚举的向量,从而最终包含不同的类型。我们已在清单8-10中对此进行了演示。

    enum SpreadsheetCell {        Int(i32),        Float(f64),        Text(String),    }    let row = vec![        SpreadsheetCell::Int(3),        SpreadsheetCell::Text(String::from("blue")),        SpreadsheetCell::Float(10.12),    ];

清单8-10:定义将一个enum不同类型的值存储在一个向量中

Rust需要知道在编译时向量中将包含哪些类型,因此Rust确切知道要存储每个元素需要多少内存。第二个优点是,我们可以明确说明此向量允许哪些类型。如果Rust允许向量保留任何类型,则一个或多个类型可能会导致对向量元素执行的操作出错。使用枚举加match表达式意味着Rust将在编译时确保处理所有可能的情况,如第6章所述。

在编写程序时,如果您不知道程序将在运行时获取的完整类型集以存储在向量中,则枚举技术将不起作用。相反,您可以使用trait对象,我们将在第17章中介绍。

现在,我们已经讨论了一些使用向量的最常用方法,请确保查看API文档中Vec有关标准库定义的所有有用方法的信息 。例如,除了push,pop 方法还删除并返回最后一个元素。让我们继续下一个集合类型:String!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值