7.1 堆上的向量(Vectors on the Heap)

The first collection type we’ll look at is Vec<T>, also known as a vector. Vectors allow you to store more than one value in a single data structure that puts all the values next to each other in memory. Vectors can only store values of the same type. They are useful when you have a list of items, such as the lines of text in a file or the prices of items in a shopping cart.

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

Vec<T> is included in the standard library prelude which means that there is no need to import it manually.

Vec<T> 包含在 标准库前置 中,这意味着无需手动导入。

创建新向量 (Creating a New Vector)

To create a new empty vector, we call the Vec::new function, as shown below:

要创建一个新的空向量,我们调用Vec::new 函数,如下所示:

    let v: Vec<u64> = Vec::new();

Note that we added a type annotation here. Because we aren’t inserting any values into this vector, the Sway compiler doesn’t know what kind of elements we intend to store. Vectors are implemented using generics which means that the Vec<T> type provided by the standard library can hold any type. When we create a vector to hold a specific type, we can specify the type within angle brackets. In the example above, we’ve told the Sway compiler that the Vec<T> in v will hold elements of the u64 type.

请注意,我们在此处添加了类型注释。因为我们没有向该向量中插入任何值,所以 Sway 编译器不知道存储何种元素。向量是用泛型实现的,这意味着标准库提供的Vec<T> 类可以包含任何类型。当我们创建一个向量来保存特定类型时,我们可以在尖括号中指定类型。在上面的示例中,我们已经告诉 Sway 编译器,v 中的Vec<T> 将保存 u64 类型的元素。

更新向量 (Updating a Vector)

To create a vector and then add elements to it, we can use the push method, as shown below:

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

    let mut v = Vec::new();

    v.push(5);
    v.push(6);
    v.push(7);
    v.push(8);

As with any variable, if we want to be able to change its value, we need to make it mutable using the mut keyword, as discussed in the section Declaring a Variable. The numbers we place inside are all of type u64, and the Sway compiler infers this from the data, so we don’t need the Vec<u64> annotation.

与任何变量一样,如果我们希望能够更改值,则需要使用 mut 关键字使其可变,如 声明变量。我们放在里面的数字都是 u64 类型,Sway 编译器从数据中推断出这一点,所以我们不需要 Vec<u64> 注释。

读取向量的元素 (Reading Elements of Vectors)

To read a value stored in a vector at a particular index, you can use the get method as shown below:

要读取存储在特定索引处的向量中的值,您可以使用 get 方法,如下所示:

    let third = v.get(2);
    match third {
        Option::Some(third) => log(third),
        Option::None => revert(42),
    }

Note two details here. First, we use the index value of 2 to get the third element because vectors are indexed by number, starting at zero. Second, we get the third element by using the get method with the index passed as an argument, which gives us an Option<T>.

这里注意两个细节。首先,我们使用 2 的索引值来获取第三个元素,因为向量是按数字索引,即从0开始。其次,我们通过使用 get 方法将索引作为参数传递来获取第三个元素,这为我们提供了 Option<T>

When the get method is passed an index that is outside the vector, it returns None without panicking. This is particularly useful if accessing an element beyond the range of the vector may happen occasionally under normal circumstances. Your code will then have logic to handle having either Some(element) or None. For example, the index could be coming as a contract method argument. If the argument passed is too large, the method get will return a None value, and the contract method may then decide to revert when that happens or return a meaningful error that tells the user how many items are in the current vector and give them another chance to pass a valid value.

当向 get 方法传递一个向量外部的索引时,它会返回 None(不会出现慌乱)。如果在正常情况下偶尔会访问超出向量范围的元素,这将特别有用。然后,您的代码将具有处理Some(element)None的逻辑。例如,索引可以作为合约方法参数出现。如果传递的参数太大,方法 get 将返回一个 None 值,然后合约方法可能决定在这种情况发生时恢复或返回一个有意义的错误,告诉用户当前向量中有多少项并给他们另一次传递有效值的机会。

迭代向量中的值 (Iterating over the Values in a Vector)

To access each element in a vector in turn, we would iterate through all of the valid indices using a while loop and the len method as shown below:

要依次访问向量中的每个元素,我们将使用 while 循环和 len 方法遍历所有有效索引,如下所示:

    let mut i = 0;
    while i < v.len() {
        log(v.get(i).unwrap());
        i += 1;
    }

Note two details here. First, we use the method len which returns the length of the vector. Second, we call the method unwrap to extract the Option returned by get. We know that unwrap will not fail (i.e. will not cause a revert) because each index i passed to get is known to be smaller than the length of the vector.

这里注意两个细节。首先,我们使用 len 方法返回向量的长度。其次,我们调用方法 unwrap 来提取 get 返回的 Option 。我们知道 unwrap 不会失败(即不会导致回撤),因为已知传递给 get 的每个索引 i 都小于向量的长度。

使用穷举存储多种类型 (Using an Enum to store Multiple Types)

Vectors can only store values that are the same type. This can be inconvenient; there are definitely use cases for needing to store a list of items of different types. Fortunately, the variants of an enum are defined under the same enum type, so when we need one type to represent elements of different types, we can define and use an enum!

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

For example, say we want to get values from a row in a table in which some of the columns in the row contain integers, some b256 values, and some Booleans. We can define an enum whose variants will hold the different value types, and all the enum variants will be considered the same type: that of the enum. Then we can create a vector to hold that enum and so, ultimately, holds different types. We’ve demonstrated this below:

例如,假设我们要从表中的一行中获取值,其中一些行的某些列包含整数、一些 b256 值和一些布尔值。我们可以定义一个穷举,其变体将包含不同的值类型,并且所有穷举变体将被视为同一类型:即穷举的类型。然后我们可以创建一个向量来保存该穷举,因此最终保存不同的类型。我们在下面证明了这一点:

    enum TableCell {
        Int: u64,
        B256: b256,
        Boolean: bool,
    }

    let mut row = Vec::new();
    row.push(TableCell::Int(3));
    row.push(TableCell::B256(0x0101010101010101010101010101010101010101010101010101010101010101));
    row.push(TableCell::Boolean(true));

Now that we’ve discussed some of the most common ways to use vectors, be sure to review the API documentation for all the many useful methods defined on Vec<T> by the standard library. For now, these can be found in the source code for Vec<T>. For example, in addition to push, a pop method removes and returns the last element, a remove method removes and returns the element at some chosen index within the vector, an insert method inserts an element at some chosen index within the vector, etc.

现在我们已经讨论了使用向量的一些最常见方法,请务必查看 API 文档来了解标准库在 Vec<T> 上定义的所有有用方法。目前,这些可以在Vec<T> 的源代码 中找到。例如,除了 push 之外,pop 方法删除并返回最后一个元素,remove 方法删除并返回向量中某个选定索引处的元素,insert 方法在某个位置插入一个元素向量中选择的索引等。

Last updated