Rust 新手编程指南 / 元组和结构体
假设我们想要从一个函数中返回多个值。举个例子,让我们创建一个函数,从一个数字向量中获取最小值、最大值以及平均值是否小于某个阈值。我们不能返回一个向量或数组,因为我们想要返回的第三个值将是一个布尔值,而另外两个将是整数,而向量和数组只能存储相同类型的值。因此,最简单的解决方案是返回一个元组。
元组只是一组值,由 () 括号组织。所以我们的函数将类似于
fn get_min_max_mean_below_threshold(input: Vec<i32>, threshold: i32) -> (i32, i32, bool) {
//to do
}
所以该函数接收一个输入值的向量和一个阈值作为输入,并返回一个包含两个整数和一个布尔值的元组作为输出。将这些作为单个函数而不是三个单独的函数的原因是,我们可以同时计算所有三个值,而只需遍历数字一次。如果我们有三个单独的函数,那么遍历所有数字三次会更慢。
fn get_min_max_mean_below_threshold(input: Vec<i32>, threshold: f64) -> (i32, i32, bool) {
let mut sum = 0;
let mut min = i32::MAX;
let mut max = i32::MIN;
for index in 0..input.len() {
let value = input[index];
sum += value;
if value < min {
min = value;
}
if value > max {
max = value;
}
}
let mean = sum as f64 / input.len() as f64;
let mut below_threshold = false;
if mean < threshold {
below_threshold = true;
}
return (min, max, below_threshold);
}
整个代码已包含在内,供您查看、检查和尝试。需要注意的是,最小值和最大值必须先有一个值,因此它们最初被设置为最大值和最小值,因此向量中的几乎任何值都会覆盖它们。对于元组来说,最重要的是我们在最后通过将它放在 () 括号中来构造元组,并将其从函数中返回。顺序很重要,因为我们使用它来从元组中获取值。在我们的主函数中,有两种方法可以获取值。以下是第一种方法
fn main() {
let values = get_min_max_mean_below_threshold(vec![10, 3, 6, 2, 7, 14], 10.0);
println!("The minimum is {}", values.0);
println!("The maximum is {}", values.1);
println!("Whether the mean was below the threshold was {}", values.2);
}
请注意,我们在 println!() 中的文本中包含其他内容,以便为不同的值提供上下文。逗号后的值将插入 {} 所在的位置。我们通过引用元组中值的索引来从元组中获取值,就像数组从 0 开始一样。但是,与数组和向量不同,我们不能使用变量来获取值,所以我们不能这样做
let index = 1;
let value = values.index;
This will not work, if you want something like this you will want an array most likely. There is another way of getting values out of a tuple:
fn main() {
let (min, max, below_threshold) = get_min_max_mean_below_threshold(vec![10, 3, 6, 2, 7, 14], 10.0);
println!("The minimum is {}", min);
println!("The maximum is {}", max);
println!("Whether the mean was below the threshold was {}", below_threshold);
}
这称为解构,因为我们模仿元组的结构,将值提取到充当任何其他变量的变量中。您可以选择哪种选项来获取值,可能取决于情况,选择最适合的选项。
但是,这有一个明显的缺点。假设我们还想获取其他值,比如众数或标准差(如果您不知道这些是什么,没关系)。一个包含太多值的元组很笨拙,因为我们必须记住所有值的顺序。最好以更结构化的方式查看一组数据的方法称为结构体。我们像这样构造/声明一个结构体
struct VectorValues {
minimum: i32,
maximum: i32,
is_below_threshold: bool,
}
由于这是一个声明,我们只指定了将放入其中的类型。然后我们将获取值的函数更改为
fn get_min_max_mean_below_threshold(input: Vec<i32>, threshold: f64) -> VectorValues {
//the inside is the same as above except for the last line
let values = VectorValues {
minimum: min,
maximum: max,
is_below_threshold: below_threshold,
};
return values;
}
现在这意味着在我们的主函数中,我们可以这样做
fn main() {
let values = get_min_max_mean_below_threshold(vec![10, 3, 6, 2, 7, 14], 10.0);
println!("The minimum is {}", values.minimum);
println!("The maximum is {}", values.maximum);
println!("Whether the mean was below the threshold was {}", values.is_below_threshold);
}
现在我们通过点后分配给它们的名字来引用结构体内的值,这应该对我们来说很有用,更令人难忘,并且在阅读时更容易理解。