6

探索 Rust:元组、数组和切片 - 强大的基础复合类型和数据引用类型 - 兰玉磊的个人博...

 11 months ago
source link: https://www.fdevops.com/2023/09/08/rust-31302
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

探索 Rust:元组、数组和切片 – 强大的基础复合类型和数据引用类型

兰玉磊 • 2023年9月8日 00:33 • Rust • 阅读 44

Rust内置两种基础复合数据类型,即元组(tuple)和数组(array)。另外,当我们需要读取和处理元组或数组时,经常使用切片(slice)这种数据类型。因此,在介绍完Rust的基础复合数据类型后,本文将进一步讨论切片类型。

这三种类型在 Rust 中都有重要的用途,元组和数组用于组织和存储数据,而切片用于访问和操作数据的部分内容。理解它们有助于编写更灵活和高效的 Rust 代码。

元组(tuple)是 Rust 内置的基础复合类型之一,它是一个有序的、固定大小的集合,可以包含不同类型的值,通过逗号分隔并用小括号括起来。元组常用于组织和返回多个值,具有静态类型安全性模式匹配的强大能力,例如 (1, "hello", 3.14) 表示一个包含整数、字符串和浮点数的元组,可以通过索引或模式匹配来访问和解构其中的元素。

fn main() {
    let person: (bool, i32, f64) = (true, 30, 5.8);
    println!("Is person adult? {}", person.0);
    // 输出:Is person adult? true
}

这里初始化了一个包含字符串、整数和浮点数的元组。

当元组中只有一个元素时,唯一的元素后面需加上逗号,否则会报警告错误:

fn main() {
    let t: (i32,) = (1,);
    println!("Hello, lanyulei! {:?}", t);
    // 输出:Hello, lanyulei! (1,)
}

访问元组元素

fn main() {
    let person: (bool, i32, f64) = (true, 30, 5.8);

    let name = person.0; // 访问第一个元素
    let age = person.1; // 访问第二个元素
    let height = person.2; // 访问第三个元素

    println!("name: {}, age: {}, height: {}", name, age, height);
}

可以使用索引来访问元组的特定元素,索引从0开始。

解构元组

fn main() {
    let person: (bool, i32, f64) = (true, 30, 5.8);

    let (name, age, height) = person; // 解构元组为单独的变量

    println!("name: {}, age: {}, height: {}", name, age, height);
    // 输出: name: true, age: 30, height: 5.8
}

这将元组的各个元素解构为单独的变量,使得你可以更方便地访问其中的数据。

模式匹配

fn main() {
    let person: (bool, i32, f64) = (true, 30, 5.8);

    match person {
        (name, age, height) => {
            println!("Name: {}, Age: {}, Height: {}", name, age, height);
            // 输出:Name: true, Age: 30, Height: 5.8
        }
    };
}

使用 match 表达式进行模式匹配,将元组的元素提取并用于不同的操作。

元组是一个灵活而强大的数据结构,常用于函数返回多个值、数据聚合和模式匹配等场景。由于其类型安全性和模式匹配的支持,元组在 Rust 中是一个非常有用的工具。

数组是 Rust 内置的基础复合类型之一,它是一个固定大小的、相同类型的元素集合,通过方括号括起来,例如 [1, 2, 3, 4, 5] 表示包含 5 个整数的数组,与元组不同,数组中所有元素必须具有相同的数据类型,且长度在创建后不可改变。数组在栈上分配内存,支持快速随机访问元素,但长度不可动态增加或减少,因此常用于对一组固定数量的数据进行存储和处理。

声明数组的语法

let array_name: [element_type; size] = [initial_values];
  • array_name 是数组的名称。
  • element_type 是数组中元素的类型,必须相同。
  • size 是数组的大小,表示数组可以容纳的元素数量。
  • initial_values 是一个可选的初始化数组的值,可以是一个包含元素的列表。如果未提供初始值,数组的元素将被初始化为默认值。

创建一个包含 5 个整数的数组并初始化为 [1, 2, 3, 4, 5]

fn main() {
    let my_array: [i32; 5] = [1, 2, 3, 4, 5];

    println!("my_array has {} elements", my_array.len());
    // 输出:my_array has 5 elements
}

访问数组元素

你可以使用索引来访问数组中的元素,索引从 0 开始计数。例如,要访问数组 my_array 中的第一个元素,可以使用 my_array[0]

fn main() {
    let my_array: [i32; 5] = [1, 2, 3, 4, 5];
    println!("my_array[0] = {}", my_array[0]);
}

你可以使用 len() 方法获取数组的长度。例如,my_array.len() 将返回 5,因为 my_array 包含 5 个元素。

fn main() {
    let my_array: [i32; 5] = [1, 2, 3, 4, 5];
    println!("my_array.len() = {}", my_array.len());
    // 输出:my_array.len() = 5
}

Rust 支持数组切片,允许你引用数组的一部分。切片是一个对数组的引用,它包括了一个范围,可以让你访问数组的特定部分。切片的语法使用 &array[start..end],其中 start 表示起始索引,end 表示结束索引(不包括结束索引处的元素)。

fn main() {
    let my_array: [i32; 5] = [1, 2, 3, 4, 5];

    // 创建一个包含 my_array 中索引 1 到 3 的元素的切片
    let my_slice: &[i32] = &my_array[1..4];

    println!("my_slice: {:?}", my_slice);
    // 输出: my_slice: [2, 3, 4]
}

数组的不可变性

在 Rust 中,默认情况下,数组是不可变的,即数组的元素不能被修改。如果你需要修改数组的元素,可以使用可变引用(&mut)来实现。

fn main() {
    let mut my_array: [i32; 5] = [1, 2, 3, 4, 5];

    my_array[0] = 10; // 修改第一个元素的值

    println!("my_array[0] = {}", my_array[0]);
    // 输出:my_array[0] = 10
}

数组的初始化

如果你不提供初始值,数组的元素将被初始化为其类型的默认值。例如,整数数组将被初始化为 0,布尔数组将被初始化为 false。

fn main() {
    let int_array: [i32; 3] = [0; 3]; // 创建一个包含 3 个 0 的整数数组
    println!("int_array: {:?}", int_array);
    // 输出:int_array: [0, 0, 0]
}

数组的遍历

你可以使用迭代器或 for 循环来遍历数组的元素。

使用迭代器:

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

    for element in my_array.iter() {
        println!("Element: {}", element);
    }
}

使用 for 循环:

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

    for i in 0..my_array.len() {
        println!("Element {}: {}", i, my_array[i]);
    }
}

数组是一种固定大小的数据结构,适用于那些在编译时已知大小的场景。如果需要在运行时动态改变大小的集合,应该使用 Rust 中的其他数据结构,如 Vec(向量)等。在使用数组时,请注意数组的长度和类型,以确保数据的完整性和类型安全性。

在 Rust 中,切片是一种引用,它允许你安全地引用数组或其他集合中的一部分元素,而不需要拷贝数据。这使得切片成为 Rust 中非常重要和灵活的数据结构之一,因为它们允许你对数据进行高效的读取和处理,同时保持所有权规则的强制执行。

切片使用起始和结束索引来定义范围,包括起始索引处的元素,但不包括结束索引处的元素。例如:[start..end]start 是切片的起始索引(包含),end 是切片的结束索引(不包含)。0..3 表示一个包含索引 0、1 和 2 对应位置元素的切片。

切片的类型是 &[T],其中 T 是切片中元素的类型。例如,&[i32] 表示一个包含 i32 类型元素的切片。

切片使得你可以轻松访问和操作集合的子集,而无需修改原始数据,是一种非常方便的数据查看工具。

切片的创建

切片可以从数组、向量或其他支持切片操作的数据结构中创建。你可以使用 & 符号将数据的引用转换为切片,或者使用 &data[start..end] 的语法来创建一个新的切片。

fn main() {
    let data = [1, 2, 3, 4, 5];
    let slice = &data[1..4]; // 创建包含 [2, 3, 4] 的切片
    println!("{:?}", slice);
    // 输出:[2, 3, 4]
}

切片的长度

切片的长度是指切片中包含的元素数量,可以通过 .len() 方法获取。

fn main() {
    let data: [i32; 5] = [1, 2, 3, 4, 5];
    let slice: &[i32] = &data[1..4];
    let length: usize = slice.len(); // 获取切片长度,此处为 3
    println!("length: {}", length);
    // 输出:length: 3
}

切片的遍历

切片可以通过 for 循环进行迭代遍历。你可以使用 iter() 方法获得切片的迭代器。

fn main() {
    let data: [i32; 5] = [1, 2, 3, 4, 5];
    let slice: &[i32] = &data[1..4];
    for item in slice.iter() {
        println!("Item: {}", item);
    }
}

可变的切片

切片是对原始数据的引用,因此它们不拥有数据的所有权。这意味着切片不能修改原始数据。如果需要可变引用,可以使用 &mut [T] 类型的可变切片。

fn main() {
    let mut data: [i32; 5] = [1, 2, 3, 4, 5];
    let slice: &mut [i32] = &mut data[1..4];
    slice[0] = 99; // 修改切片中的元素,data 变为 [1, 99, 3, 4, 5]
    println!("{:?}", data);
    // 输出:[1, 99, 3, 4, 5]
}

切片的借用规则

在 Rust 中,切片的引用规则遵循借用规则,即在同一作用域内,要么有一个可变引用,要么有多个不可变引用,但不能同时存在可变引用和不可变引用。

字符串切片

在 Rust 中,字符串切片是一种特殊类型的切片,通常用 &str 表示。其中 & 表示引用,而 str 表示字符串切片的类型。

字符串切片是对字符串数据的引用,允许你引用字符串中的一部分字符序列,而无需拥有整个字符串的所有权。

字符串切片是 Rust 中处理文本数据的重要工具。

字符串切片可以从字符串字面值、String 类型的字符串或其他字符串切片中创建。你可以使用 & 符号将字符串引用转换为字符串切片,或者通过切片语法 &string[start..end] 来创建一个新的字符串切片。

fn main() {
    let string_literal: &str = "Hello, lanyulei!"; // 从字符串字面值创建字符串切片
    println!("{}", string_literal);
    // 输出:Hello, lanyulei!

    let string_data: String = String::from("Rust is great!");
    let slice: &str = &string_data; // 从 String 创建字符串切片
    println!("{}", slice);
    // 输出:Rust is great!

    let sub_slice: &str = &slice[0..4]; // 通过切片语法 &string[start..end] 来创建一个新的字符串切片,创建包含 "Rust" 的字符串切片
    println!("{}", sub_slice);
    // 输出:Rust
}

字符串切片是不可变的,这意味着你不能修改字符串切片中的字符。

字符串的不可变性在 Rust 中是强制执行的,哪怕是使用了 mut 关键字仍然是不可变的,这有助于防止一些常见的编程错误。

fn main() {
    let mut string_data: &str = "Hello lanyulei!";
    // 下面的代码尝试修改字符串切片中的字符,会导致编译错误
    // string_data[0] = 'h'; // 无法编译,因为字符串切片是不可变的
}

你可以使用 .len() 方法获取字符串切片的长度,以及使用迭代器进行字符遍历。

fn main() {
    let text: &str = "Rust is great!";
    let length: usize = text.len(); // 获取字符串切片的长度
    println!("length: {}", length);
    // 输出: length: 14

    // 使用 `chars` 方法迭代字符串切片中的字符
    for c in text.chars() {
        println!("Character: {}", c);
    }
}

字符串切片与模式匹配结合使用非常有用,允许你根据字符串内容执行不同的操作。

fn main() {
    let text: &str = "Rust";
    match text {
        "Rust" => println!("Found Rust!"),
        "Java" => println!("Found Java!"),
        _ => println!("Not found"),
    }
}

字符串切片在 Rust 中广泛用于文本处理、字符串搜索、解析和分割等操作。由于其不可变性和引用语义,它们是编写安全且高性能的代码的关键组成部分。在处理字符串时,使用字符串切片通常比拥有整个字符串的所有权更高效,因为不需要复制字符串的内容。因此,字符串切片是 Rust 中处理字符串数据的常见选择。

切片的模式匹配

切片可以与模式匹配结合使用,允许你根据切片的内容执行不同的操作。

fn main() {
    let data: [i32; 5] = [1, 2, 3, 4, 5];
    let slice: &[i32] = &data[1..4];
    match slice {
        [2, 3, 4] => println!("Matched [2, 3, 4]"),
        _ => println!("Not matched"),
    }
}

总而言之,切片是 Rust 中用于引用集合部分数据的强大工具,它们允许你在不拥有所有权的情况下有效地操作和处理数据。切片在许多 Rust 代码中都有广泛的应用,特别是在处理字符串和集合数据时。

在 Rust 中,元组、数组和切片是强大而灵活的工具,用于组织、存储和操作数据。它们使得编写安全、高效的 Rust 代码变得更加容易。无论是元组的多功能性、数组的固定大小特性,还是切片的数据引用和模式匹配能力,都为你的编程提供了丰富的选择。

无论你是在处理多个值、存储数据集合还是进行文本处理,都可以根据具体情况选择合适的数据类型。并且不要忘记 Rust 的所有权和借用规则,它们确保了代码的安全性和可靠性。

最后,祝愿你在 Rust 的编程之旅中取得成功,创造出令人惊叹的应用程序和项目!继续享受 Rust 编程的乐趣吧!

本文为原创文章,未经授权禁止转载本站文章。
原文出处:兰玉磊的个人博客
原文链接:https://www.fdevops.com/2023/09/08/rust-31302
版权:本文采用「署名-非商业性使用-相同方式共享 4.0 国际」知识共享许可协议进行许可。


Recommend

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK