Rust 基础系列 #4: Rust 中的数组和元组
Rust
![](/data/attachment/album/202305/23/165645ljp41i87p7xcpx1z.jpg)



> 
> 在 Rust 系列的第四篇中，学习复合数据类型、数组和元组。
> 
> 
> 


在上一篇文章中，你学习到了 Rust 中的 [标量数据类型](/article-15811-1.html)。它们是整型、浮点数、字符和布尔值。


在本文中，我们将会看看 Rust 编程语言中的复合数据类型。


### Rust 中的复合数据类型是什么？


复合数据类型可以在一个变量中存储多个值。这些值可以是相同的标量数据类型，也可以是不同的标量数据类型。


Rust 编程语言中有两种这样的数据类型：


* <ruby> 数组 <rt>  Array </rt></ruby>：存储相同类型的多个值。
* <ruby> 元组 <rt>  Tuple </rt></ruby>：存储多个值，可以是相同的类型，也可以是不同的类型。


让我们了解一下它们吧！


### Rust 中的数组


Rust 编程语言中的数组具有以下特性：


* 每一个元素都必须是相同的类型
* 数组有一个固定的长度
* 数组存储在堆栈中，即其中存储的数据可以被 *迅速* 访问


创建数组的语法如下：



```
// 无类型声明
let variable_name = [element1, element2, ..., elementn];

// 有类型声明
let variable_name: [data_type; array_length] = [element1, element2, ..., elementn];

```

数组中的元素是在方括号中声明的。要访问数组的元素，需要在方括号中指定要访问的索引。


来让我们看一个例子来更好地理解这个。



```
fn main() {
    // 无类型声明
    let greeting = ['H', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', '!'];

    // 有类型声明
    let pi: [i32; 10] = [1, 4, 1, 5, 9, 2, 6, 5, 3, 5];

    for character in greeting {
        print!("{}", character);
    }

    println!("\nPi: 3.1{}{}{}{}", pi[0], pi[1], pi[2], pi[3]);
}

```

这里，我定义了一个字符数组和另一个存储 `i32` 类型的值的数组。`greeting` 数组以单独字符的形式存储了字符串 `"Hello world!"` 的字符。`pi` 数组以单独数字的形式存储了圆周率小数点后的前 10 位数字。


然后，我使用 `for` 循环打印了 `greeting` 数组的每个字符。（我很快就会讲到循环。）然后，我打印了 `pi` 数组的前 4 个值。



```
Hello world!
Pi: 3.11415

```

如果你想创建一个数组，其中每个元素都是 *y*，并且出现 *x* 次，你可以使用以下快捷方式在 Rust 中实现：



```
let variable_name = [y; x];

```

来看一个演示……



```
fn main() {
    let a = [10; 5];

    for i in a {
        print!("{i} ");
    }
    println!("");
}

```

我创建了一个变量 `a`，它的长度为 5。数组中的每个元素都是 '10'。我通过使用 `for` 循环打印数组的每个元素来验证这一点。


它的输出如下：



```
10 10 10 10 10

```


> 
> ? 作为练习，尝试创建一个长度为 *x* 的数组，然后尝试访问数组的第 *x+1* 个元素。看看会发生什么。
> 
> 
> 


### Rust 中的元组


Rust 中的元组具有以下特性：


* 就像数组一样，元组的长度是固定的
* 元素可以是相同的/不同的标量数据类型
* 元组存储在堆栈中，所以访问速度更快


创建元组的语法如下：



```
// 无类型声明
let variable_name = (element1, element2, ..., element3);

// 有类型声明
let variable_name: (data_type, ..., data_type) = (element1, element2, ..., element3);

```

元组的元素写在圆括号中。要访问元素，使用点运算符，后跟该元素的索引。



```
fn main() {
    let a = (38, 923.329, true);
    let b: (char, i32, f64, bool) = ('r', 43, 3.14, false);

    println!("a.0: {}, a.1: {}, a.2: {}", a.0, a.1, a.2);
    println!("b.0: {}, b.1: {}, b.2: {}, b.3: {}", b.0, b.1, b.2, b.3);

    // 元组解构
    let pixel = (50, 0, 200);
    let (red, green, blue) = pixel;
    println!("red: {}, green: {}, blue: {}", red, green, blue);
}

```

在上面的代码中，我在第 2 行和第 3 行声明了两个元组。它们只包含我当时想到的随机值。但是仔细看，两个元组中每个元素的数据类型都不同。然后，在第 5 行和第 6 行，我打印了两个元组的每个元素。


在第 9 行，我声明了一个名为 `pixel` 的元组，它有 3 个元素。每个元素都是组成像素的颜色红色、绿色和蓝色的亮度值。这个范围是从 0 到 255。所以，理想情况下，我会声明类型为 `(u8, u8, u8)`，但是在学习代码时不需要这样优化 ; )


然后，在第 10 行，我“解构”了 `pixel` 元组的每个值，并将其存储在单独的变量 `red`、`green` 和 `blue` 中。然后，我打印了 `red`、`green` 和 `blue` 变量的值，而不是 `pixel` 元组的值。


让我们看看输出……



```
a.0: 38, a.1: 923.329, a.2: true
b.0: r, b.1: 43, b.2: 3.14, b.3: false
red: 50, green: 0, blue: 200

```

看起来不错 : )


### 额外内容：切片


准确的来说，<ruby> 切片 <rt>  Slice </rt></ruby> 不是 Rust 中的复合数据类型。相反，切片是现有复合数据类型的 “切片”。


一个切片由三个元素组成：


* 一个初始索引
* 切片运算符（`..` 或 `..=`）
* 一个结束索引


接下来是数组切片的一个示例：



```
fn main() {
    let my_array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
    let my_slice = &my_array[0..4];

    for element in my_slice {
        println!("{element}");
    }
}

```

就像 C 和 C++ 一样，`&` 用于存储变量的引用（而不是原始指针）。所以 `&my_array` 意味着对变量 `my_array` 的引用。


然后，来看看切片。切片由 `[0..4]` 表示。这里，`0` 是切片开始的索引。而 `4` 是切片结束的索引。这里的 4 是一个非包含索引。


这是程序输出，以更好地理解正在发生的事情：



```
0
1
2
3

```

如果你想要一个 *包含* 范围，你可以使用 `..=` 作为包含范围的切片运算符。



```
fn main() {
    let my_array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
    let my_slice = &my_array[0..=4];

    for element in my_slice {
        println!("{element}");
    }
}

```

现在，这个范围是从第 0 个元素到第 4 个元素，下面是输出来证明这一点：



```
0
1
2
3
4

```

### 总结


本文讲到了 Rust 编程语言中的复合数据类型。你学习了如何声明和访问存储在数组和元组类型中的值。此外，你还了解了切片“类型”，以及如何解构元组。


在下一章中，你将学习如何在 Rust 程序中使用函数。敬请关注。


*（题图：MJ/22a0d143-2216-439f-8e1d-abd94cdfdbd0）*




---


via: <https://itsfoss.com/rust-arrays-tuples/>


作者：[Pratham Patel](https://itsfoss.com/author/pratham/) 选题：[lkxed](https://github.com/lkxed/) 译者：[Cubik65536](https://github.com/Cubik65536) 校对：[wxy](https://github.com/wxy)


本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


OK
# Rust Basics Series #4: Arrays and Tuples in Rust

In the fourth chapter of the Rust series, learn about compound data types, Arrays and Tuples.

In the previous post, you learned about the [Scalar data types in Rust](https://itsfoss.com/rust-data-types/). They are integers, floating points, characters and booleans.

In this article, we shall look at the Compound data types in the Rust programming language.

## What is compound data type in Rust?

Compound data types consist can store multiple values in a variable. These values may either be of the same scalar data type, or maybe of different scalar types.

The Rust programming language has two such data types:

**Arrays**: Stores multiple values of the same type.**Tuples**: Stores multiple values, either of the same type or even of different types.

So let's look at them!

## Arrays in Rust

Arrays in the Rust programming language have the following properties:

- Every element must have the same type
- Arrays have a fixed length
- Arrays are stored in the stack i.e., data stored in it can be accessed
*swiftly*

The syntax to create an array is as follows:

```
// without type annotation
let variable_name = [element1, element2, ..., elementn];
// with type annotation
let variable_name: [data_type; array_length] = [element1, element2, ..., elementn];
```


The elements of an array are declared inside square brackets. To access an element of an array, the index to be accessed is specified inside square brackets.

Let's look at an example program to understand this better.

```
fn main() {
// without type annotation
let greeting = ['H', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', '!'];
// with type annotation
let pi: [i32; 10] = [1, 4, 1, 5, 9, 2, 6, 5, 3, 5];
for character in greeting {
print!("{}", character);
}
println!("\nPi: 3.1{}{}{}{}", pi[0], pi[1], pi[2], pi[3]);
}
```


Here, I define one character array and another array that stores `i32`

types in it. The `greeting`

array has the characters of the string "Hello world!" stored in it as individual characters. The array `pi`

has the first 10 values of Pi after the decimal values stored in it as individual numbers.

I then print every character of the `greeting`

array using the `for`

loop. (I will get into loops very soon.) Then, I print the first 4 values of the `pi`

array.

```
Hello world!
Pi: 3.11415
```


If you wish to create an array where every element is *y* and occours *x* number of times, you can do this in Rust with the following shortcut:

`let variable_name = [y; x];`


Let's look at a demonstration...

```
fn main() {
let a = [10; 5];
for i in a {
print!("{i} ");
}
println!("");
}
```


I create a variable `a`

which will be of length 5. Each element in that array will be '10'. I verify this by printing every element of the array using the `for`

loop.

It has the following output:

`10 10 10 10 10`


*and access the*

*x*

*x+1**element of the array. See what happens.*

*st*## Tuples in Rust

A Tuple in the Rust programming language has the following properties:

- Tuples, like Arrays have a fixed length
- Elements can be of same/different Scalar data types
- The Tuple is stored on the stack i.e. faster access

The syntax to create a tuple is as following:

```
// without type annotation
let variable_name = (element1, element2, ..., element3);
// with type annotation
let variable_name: (data_type, ..., data_type) = (element1, element2, ..., element3);
```


The elements of a tuple are written inside the round brackets. To access an element, the dot operator is used and is followed by the index of said element.

```
fn main() {
let a = (38, 923.329, true);
let b: (char, i32, f64, bool) = ('r', 43, 3.14, false);
println!("a.0: {}, a.1: {}, a.2: {}", a.0, a.1, a.2);
println!("b.0: {}, b.1: {}, b.2: {}, b.3: {}", b.0, b.1, b.2, b.3);
// destructuring a tuple
let pixel = (50, 0, 200);
let (red, green, blue) = pixel;
println!("red: {}, green: {}, blue: {}", red, green, blue);
}
```


In the above code, on line 2 and 3 I declare two tuples. These just contain random values that I made up on the spot. But look closely, the data type of each element in both tuples is different. Then, on line 5 and 6, I print each element of both tuples.

On line 9, I declare a tuple called `pixel`

which has 3 elements. Each element is the magnitude of colors red, green and blue to make up a pixel. This ranges from 0 to 255. So, ideally, I would annotate the type to be `(u8, u8, u8)`

but that optimization is not required when learning ;)

Then, on line 10, I "de-structure" each value of the `pixel`

tuple and store it in individual variables `red`

, `green`

and `blue`

. Then, instead of printing the values of the `pixel`

tuple, I print the values of the `red`

, `green`

and `blue`

variables.

Let's see the output...

```
a.0: 38, a.1: 923.329, a.2: true
b.0: r, b.1: 43, b.2: 3.14, b.3: false
red: 50, green: 0, blue: 200
```


Looks good to me :)

## Bonus: Slices

Strictly speaking, slices aren't a type of compound data type in Rust. Rather, a slice is... a *slice* of an existing compound data type.

A slice consists of three elements:

- A starting index
- The slice operator (
`..`

or`..=`

) - An ending index

Following is an example of using a slice of an Array.

```
fn main() {
let my_array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
let my_slice = &my_array[0..4];
for element in my_slice {
println!("{element}");
}
}
```


Like C and C++, the ampersand is used to store the reference (instead of a raw pointer) of a variable. So `&my_array`

means a reference to the variable `my_array`

.

Now, coming to the slice. The slice is denoted by the `[0..4]`

. Here, `0`

is the index of where to start the slice. And `4`

is where the slice ends. The 4 here is a non-inclusive index.

Following is the program output to better understand what is happening:

```
0
1
2
3
```


If you want an *inclusive* range, you can instead use `..=`

as the slice operator for an inclusive range.

```
fn main() {
let my_array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
let my_slice = &my_array[0..=4];
for element in my_slice {
println!("{element}");
}
}
```


Now, this range is from the 0th element to the 4th element and below is the output to prove that:

```
0
1
2
3
4
```


## Conclusion

This article about the Rust programming language covers the compound data types in some depth. You learned to declare and access values stored in the Array and Tuple types. Additionally, you looked at the Slice "type" and also how to de-structure a tuple.

In the next chapter, you'll learn about using functions in Rust programs.

[Rust Basics Series #5: Functions in RustIn this chapter of the Rust Basics series, learn to use functions and return values from them with the help of examples.](https://itsfoss.com/rust-functions/)![](https://itsfoss.com/content/images/2023/04/functions-in-rust-programming-language.png)


![](https://itsfoss.com/content/images/2023/04/functions-in-rust-programming-language.png)

Stay tuned.