小白教程
所有教程
关于
Search
172.70.179.121
172.70.179.121
参数设置
贡献
退出
操作
编辑
移动
保护
信息
历史
删除
查看“Rust 集合与字符串”的源代码
本页内容
上一节:
Rust_文件与_IO
下一节:
Rust_面向对象
因为以下原因,您没有权限编辑本页:
您请求的操作仅限属于该用户组的用户执行:
用户
您可以查看和复制此页面的源代码。
{{DISPLAYTITLE:Rust 集合与字符串}}[[Category:Rust 教程|20]] = Rust 集合与字符串 = 集合(Collection)是数据结构中最普遍的数据存放形式,Rust 标准库中提供了丰富的集合类型帮助开发者处理数据结构的操作。 === 向量 === 向量(Vector)是一个存放多值的单数据结构,该结构将相同类型的值线性的存放在内存中。 向量是线性表,在 Rust 中的表示是 Vec<T>。 向量的使用方式类似于列表(List),我们可以通过这种方式创建指定类型的向量: <pre>let vector: Vec<i32> = Vec::new(); // 创建类型为 i32 的空向量 let vector = vec![1, 2, 4, 8]; // 通过数组创建向量</pre> 我们使用线性表常常会用到追加的操作,但是追加和栈的 push 操作本质是一样的,所以向量只有 push 方法来追加单个元素: <sample title="" desc="" lang="rust" hererun="1"> fn main() { let mut vector = vec![1, 2, 4, 8]; vector.push(16); vector.push(32); vector.push(64); println!("{:?}", vector); } </sample> 运行结果: <pre> [1, 2, 4, 8, 16, 32, 64]</pre> append 方法用于将一个向量拼接到另一个向量的尾部: <sample title="" desc="" lang="rust" hererun="1"> fn main() { let mut v1: Vec<i32> = vec![1, 2, 4, 8]; let mut v2: Vec<i32> = vec![16, 32, 64]; v1.append(&mut v2); println!("{:?}", v1); } </sample> 运行结果: <pre> [1, 2, 4, 8, 16, 32, 64]</pre> get 方法用于取出向量中的值: <sample title="" desc="" lang="rust" hererun="1"> fn main() { let mut v = vec![1, 2, 4, 8]; println!("{}", match v.get(0) { Some(value) => value.to_string(), None => "None".to_string() }); } </sample> 运行结果: <pre>1</pre> 因为向量的长度无法从逻辑上推断,get 方法无法保证一定取到值,所以 get 方法的返回值是 Option 枚举类,有可能为空。 这是一种安全的取值方法,但是书写起来有些麻烦。如果你能够保证取值的下标不会超出向量下标取值范围,你也可以使用数组取值语法: <sample title="" desc="" lang="rust" hererun="1"> fn main() { let v = vec![1, 2, 4, 8]; println!("{}", v[1]); } </sample> 运行结果: <pre>2</pre> 但如果我们尝试获取 v[4] ,那么向量会返回错误。 遍历向量: <sample title="" desc="" lang="rust" hererun="1"> fn main() { let v = vec![100, 32, 57]; for i in &v { println!("{}", i); } } </sample> 运行结果: <pre>100 32 57</pre> 如果遍历过程中需要更改变量的值: <sample title="" desc="" lang="rust" hererun="1"> fn main() { let mut v = vec![100, 32, 57]; for i in &mut v { *i += 50; } } </sample> == 字符串 == 字符串类(String)到本章为止已经使用了很多,所以有很多的方法已经被读者熟知。本章主要介绍字符串的方法和 UTF-8 性质。 新建字符串: <pre> let string = String::new();</pre> 基础类型转换成字符串: <pre>let one = 1.to_string(); // 整数到字符串 let float = 1.3.to_string(); // 浮点数到字符串 let slice = "slice".to_string(); // 字符串切片到字符串</pre> 包含 UTF-8 字符的字符串: <pre>let hello = String::from("السلام عليكم"); let hello = String::from("Dobrý den"); let hello = String::from("Hello"); let hello = String::from("שָׁלוֹם"); let hello = String::from("नमस्ते"); let hello = String::from("こんにちは"); let hello = String::from("안녕하세요"); let hello = String::from("你好"); let hello = String::from("Olá"); let hello = String::from("Здравствуйте"); let hello = String::from("Hola");</pre> 字符串追加: <pre>let mut s = String::from("run"); s.push_str("oob"); // 追加字符串切片 s.push('!'); // 追加字符</pre> 用 + 号拼接字符串: <pre>let s1 = String::from("Hello, "); let s2 = String::from("world!"); let s3 = s1 + &s2;</pre> 这个语法也可以包含字符串切片: <pre>let s1 = String::from("tic"); let s2 = String::from("tac"); let s3 = String::from("toe"); let s = s1 + "-" + &s2 + "-" + &s3;</pre> 使用 format! 宏: <pre>let s1 = String::from("tic"); let s2 = String::from("tac"); let s3 = String::from("toe"); let s = format!("{}-{}-{}", s1, s2, s3);</pre> 字符串长度: <pre>let s = "hello"; let len = s.len();</pre> 这里 len 的值是 5。 <pre>let s = "你好"; let len = s.len();</pre> 这里 len 的值是 6。因为中文是 UTF-8 编码的,每个字符长 3 字节,所以长度为6。但是 Rust 中支持 UTF-8 字符对象,所以如果想统计字符数量可以先取字符串为字符集合: <pre>let s = "hello你好"; let len = s.chars().count();</pre> 这里 len 的值是 7,因为一共有 7 个字符。统计字符的速度比统计数据长度的速度慢得多。 遍历字符串: <sample title="" desc="" lang="rust" hererun="1"> fn main() { let s = String::from("hello中文"); for c in s.chars() { println!("{}", c); } } </sample> 运行结果: <pre>h e l l o 中 文</pre> 从字符串中取单个字符: <sample title="" desc="" lang="rust" hererun="1"> fn main() { let s = String::from("EN中文"); let a = s.chars().nth(2); println!("{:?}", a); } </sample> 运行结果: <pre>Some('中')</pre> '''注意''':nth 函数是从迭代器中取出某值的方法,请不要在遍历中这样使用!因为 UTF-8 每个字符的长度不一定相等! 如果想截取字符串字串: <sample title="" desc="" lang="rust" hererun="1"> fn main() { let s = String::from("EN中文"); let sub = &s[0..2]; println!("{}", sub); } </sample> 运行结果: <pre>EN</pre> 但是请注意此用法有可能肢解一个 UTF-8 字符!那样会报错: <sample title="" desc="" lang="rust" hererun="1"> fn main() { let s = String::from("EN中文"); let sub = &s[0..3]; println!("{}", sub); } </sample> 运行结果: <pre>thread 'main' panicked at 'byte index 3 is not a char boundary; it is inside '中' (bytes 2..5) of `EN中文`', src\libcore\str\mod.rs:2069:5 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.</pre> == 映射表 == 映射表(Map)在其他语言中广泛存在。其中应用最普遍的就是键值散列映射表(Hash Map)。 新建一个散列值映射表: <sample title="" desc="" lang="rust" hererun="1"> use std::collections::HashMap; fn main() { let mut map = HashMap::new(); map.insert("color", "red"); map.insert("size", "10 m^2"); println!("{}", map.get("color").unwrap()); } </sample> '''注意''':这里没有声明散列表的泛型,是因为 Rust 的自动判断类型机制。 运行结果: <pre>red</pre> insert 方法和 get 方法是映射表最常用的两个方法。 映射表支持迭代器: <sample title="" desc="" lang="rust" hererun="1"> use std::collections::HashMap; fn main() { let mut map = HashMap::new(); map.insert("color", "red"); map.insert("size", "10 m^2"); for p in map.iter() { println!("{:?}", p); } } </sample> 运行结果: <pre>("color", "red") ("size", "10 m^2")</pre> 迭代元素是表示键值对的元组。 Rust 的映射表是十分方便的数据结构,当使用 insert 方法添加新的键值对的时候,如果已经存在相同的键,会直接覆盖对应的值。如果你想"安全地插入",就是在确认当前不存在某个键时才执行的插入动作,可以这样: <pre>map.entry("color").or_insert("red");</pre> 这句话的意思是如果没有键为 "color" 的键值对就添加它并设定值为 "red",否则将跳过。 在已经确定有某个键的情况下如果想直接修改对应的值,有更快的办法: <sample title="" desc="" lang="rust" hererun="1"> use std::collections::HashMap; fn main() { let mut map = HashMap::new(); map.insert(1, "a"); if let Some(x) = map.get_mut(&1) { *x = "b"; } } </sample>
返回至“
Rust 集合与字符串
”。
上一节:
Rust_文件与_IO
下一节:
Rust_面向对象