rust容器

标准库提供了常见的容器。包括向量 ( Vector )、映射( HashMap )、集合( HashSet )。

一、向量Vector

数组有一个缺点,就是它的长度在编译时就确定了,一旦确定就永不可更改。
向量是一个长度可变的数组。向量的存储在堆上,因此长度可变。

Rust在标准库中定义了结构体Vec用于表示向量。

(一)定义向量
一维向量
1.new()创建一个空向量
语法格式

let mut instance_name: Vec<T> = Vec::new();
例子
let v1: Vec<i32> = Vec::new(); // 创建类型为i32的空向量

2.vec!()宏创建向量
这种方式的创建方法类似于数组的语法。
它也有3种创建方式。
(1)创建空向量。需要指定类型。

let mut vec_marco: Vec<i32> = vec![];

(2)指定所有元素。可以省略类型。

let mut vec_marco = vec![1, 2, 3, 4, 5];

(3)指定初始值和长度。可以省略类型。

let mut vec_marco = vec![0; 5];     // 长度为5,元素初始化为0

注意,长度可以是变量,这点与数组不同。
例子

let len = 10;
let zero_vec = vec![0; len];

3.从数组创建向量

let arr = [1, 2, 3, 4, 5];
let v = arr.to_vec();

二维向量
1.使用new()创建空向量。需要指定类型。

let mut instance_name: Vec<Vec<T>> = Vec::new();
例子
let v1: Vec<Vec<i32>> = Vec::new();

2.使用vec!()宏创建向量
(1)创建空向量。需要指定类型。

let mut vec_marco: Vec<Vec<i32>> = vec![];

(2)指定所有元素。可以省略类型。

let mut vec_marco = vec![vec![1, 2, 3, 4, 5], ...];

(3)指定初始值和长度。可以省略类型。

let mut vec_marco = vec![vec![0; 5]; 10];
例子
let width = 4;
let height = 4;
let mut array = vec![vec![0; width]; height];

3.从二维数组创建二维向量
例如

let s = [
[0, 0, 1, 0, 0],
[0, 0, 1, 0, 0],
[0, 0, 1, 0, 0],
[0, 0, 1, 0, 0],
];
let s: Vec<_> = s.iter().map(|&e| e.to_vec()).collect();

(二)使用向量
1.获取长度
len()方法
例子

fn main() {
    let v = vec![1, 2, 3];
    println!("{}", v.len());
    let width = 4;
    let height = 4;
    let array = vec![vec![0; width]; height];
    println!("{} {}", array.len(), array[0].len());
}
运行结果如下
3
4 4

2.添加元素
使用push方法来追加单个元素
实例

fn main() {
    let mut vector = vec![1, 2, 4, 8];
    vector.push(16);
    vector.push(32);
    vector.push(64);
    println!("{:?}", vector);
    let mut arr: Vec<Vec<i32>> = Vec::new();
    arr.push(Vec::new());
    arr.push(vec![]);
    arr[0].push(1);
    println!("{:?}", arr);
}
运行结果:
[1, 2, 4, 8, 16, 32, 64]
[[1], []]

使用append方法用于将一个向量拼接到另一个向量的尾部
实例

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);
}
运行结果:
[1, 2, 4, 8, 16, 32, 64]

2.删除元素
使用remove()删除元素
remove() 方法移除并返回向量中指定的下标索引处的元素,将其后面的所有元素移到向左移动一位。

fn main() {
    let mut v = vec![10,20,30];
    v.remove(1);
    println!("{:?}",v);
}
运行结果如下
[10, 30]

clear
删除所有元素

let mut v = vec![10,20,30];
v.clear();
println!("{:?}",v);

3.获取元素
因为向量实现了Deref Target=[T],所以向量自动实现了切片的所有方法。
(1)使用get方法
get方法根据索引返回对元素或子切片的引用。
如果给定位置,则返回该位置上的元素的引用,如果越界则返回None。
如果给定范围,则返回对应于该范围的子切片,如果越界则返回None。
例子

let v = vec![10, 40, 30];
assert_eq!(Some(&40), v.get(1));
assert_eq!(Some(&[10, 40][..]), v.get(0..2));
assert_eq!(None, v.get(3));
assert_eq!(None, v.get(0..4));

(2)get_mut
get_mut方法根据索引返回对元素或子切片的可变引用
如果给定位置,则返回该位置上的元素的可变引用,如果越界则返回None。
如果给定范围,则返回对应于该范围的可变子切片,如果越界则返回None。
例子

let mut x = vec![0, 1, 2];
if let Some(elem) = x.get_mut(1) {
    *elem = 42;
}
assert_eq!(x, &[0, 42, 2]);

(3)使用[]
实例

fn main() {
    let v = vec![1, 2, 4, 8];
    println!("{}", v[1]);
}
运行结果:
2

二维向量

array[2][2] = 5;
println!("{:?}", array);

例子

use std::io;
fn main(){
    let width = 4;
    let height = 4;
    let mut array = vec![vec![0; width]; height];
    for i in 0..4 {
         let mut buf = String::from("");
         io::stdin().read_line(&mut buf).unwrap();
         array[i] = buf.split_whitespace().map(|s| s.parse().unwrap()).collect();
    }
    println!("{:?}", array);
}

4.遍历向量
(1)使用索引

fn main() {
    let v = vec![100, 32, 57];
    for i in 0..v.len() {
            println!("{}", v[i]);
    }
}

(2)使用向量的引用
实例

fn main() {
    let v = vec![100, 32, 57];
    for i in &v {
            println!("{}", i);
    }
}
运行结果:
100
32
57

实例

fn main() {
    let mut v = vec![100, 32, 57];
    for i in &mut v {
        *i += 50;
    }
    println!("{:?}", v);
}

(3)使用迭代器
iter()返回一个只读迭代器

for num in nums1.iter() {
     print!("{} ", num);
}
println!();

iter_mut()返回一个可写迭代器

let mut nums1 = [1; 5];
let mut i = 0;
for num in nums1.iter_mut() {
     *num = i;
     i += 1;
}
println!("{:?}", nums1);

into_iter()返回一个迭代器,但是转让所有权

let mut nums1 = [1; 5];
for num in nums1.into_iter() {
    print!("{} ", num);
}
println!();

for num in nums1.into_iter()
实际上等价于
for num in nums1

(4)使用迭代器的enumerate

let mut nums1 = [1; 5];
for (pos, v) in nums1.iter().enumerate() {
    println!("nums[{}]={}", pos, v);
}
println!("{:?}", nums1);
for (pos, v) in nums1.iter_mut().enumerate() {
    *v=pos;
    println!("nums[{}]={}", pos, v);
}
println!("{:?}", nums1);

二维向量
(1)使用索引

let mut v = vec![vec![1, 2, 3, 4, 5], vec![3, 9, 8]];
for i in 0..v.len() {
    for j in 0..v[i].len() {
         println!("{}", v[i][j]);
    }
}

(2)使用引用
例子

let s = [
[0, 0, 1, 0, 0],
[0, 0, 1, 0, 0],
[0, 0, 1, 0, 0],
[0, 0, 1, 0, 0],
];
let mut s: Vec<_> = s.iter().map(|&e| e.to_vec()).collect();
for row in &s{
    for col in row{
         print!("{} ", col);
    }
    println!();
}
for row in &mut s {
    for col in row {
         *col += 1;
         print!("{} ", col);
    }
    println!();
}

(3)使用向量的迭代器

let mut grid = [[0; 5]; 5];
for row in grid.iter() {
    for col in row.iter() {
         print!("{} ", col);
    }
    println!();
}
let mut i = 0;
for row in grid.iter_mut(){
    for col in row.iter_mut() {
         *col = i;
         i += 1;
         print!("{} ", col);
    }
    println!();
}

(4)使用迭代器的enumerate

let mut grid = [[0; 5]; 5];
for (i, row) in grid.iter().enumerate() {
    for (j, col) in row.iter().enumerate() {
         print!("{}", col);
    }
    println!()
}
for (i, row) in grid.iter_mut().enumerate() {
    for (j, col) in row.iter_mut().enumerate() {
         *col = 1;
    }
}

6.使用contains() 判断向量是否包含某个元素
如果值在向量中存在则返回 true ,否则返回 false 。

fn main() {
     let v = vec![10,20,30];
     if v.contains(&10) {
         println!("found 10");
     }
     println!("{:?}",v);
}
运行结果如下
found 10
[10, 20, 30]

7.逆转向量

reverse
适当地反转切片中元素的顺序。
例子
let mut v = [1, 2, 3];
v.reverse();
assert!(v == [3, 2, 1]);

二、映射HashMap

映射表(Map)在其他语言中广泛存在。其中应用最普遍的就是散列映射表(Hash Map)。
HashMap就是 键值对 的集合。映射表中不允许有重复的键,但允许不同的键有相同的值。

Rust语言定义了HashMap结构体来表示映射表。
HashMap结构体定义在std::collections模块中,使用之前需要导入std::collections模块。

(一)定义映射表
1.使用new创建空映射表
语法格式如下

let mut instance_name: HashMap<type1, type2> = HashMap::new();

实例

use std::collections::HashMap;
let mut map: HashMap<&str, i32> = HashMap::new();
let mut map = HashMap::new();//可以省略类型

2.可以从数组初始化HashMap
例子

use std::collections::HashMap;
let solar_distance = HashMap::from([
("Mercury", 0.4),
("Venus", 0.7),
("Earth", 1.0),
("Mars", 1.5),
]);

(二)使用映射表
1.使用len()获取键值对的个数
例子

use std::collections::HashMap;
fn main() {
     let mut stateCodes = HashMap::new();
     stateCodes.insert("name","简单教程");
     stateCodes.insert("site","https://www.twle.cn");
     println!("size of map is {}",stateCodes.len());
}
编译运行结果如下
size of map is 2

2.添加键值对
使用insert()方法用于插入或更新一个键值对
如果键已经存在,则更新为新的值,并则返回旧的值。
如果键不存在则执行插入操作并返回None 。

例子

fn main() {
    let mut map = HashMap::new();
    map.insert("color", "red");
    map.insert("size", "10 m^2");
    println!("{}", map.get("color").unwrap());
}
运行结果:
red

3.删除指定键值对
remove()用于从映射表中删除指定的键值对。
如果键值对存在则返回删除的键值对,返回的数据格式为 (&'a K, &'a V) 。
如果键值对不存在则返回None

例子

use std::collections::HashMap;
fn main() {
     let mut stateCodes = HashMap::new();
     stateCodes.insert("name","简单教程");
     stateCodes.insert("site","https://www.twle.cn");
     stateCodes.insert("slogn","简单教程,简单编程");
     println!("length of the hashmap {}",stateCodes.len());
     stateCodes.remove(&"site");
     println!("length of the hashmap after remove() {}",stateCodes.len());
}
编译运行结果如下
length of the hashmap 3
length of the hashmap after remove() 2

clear
清除map,删除所有键值对。
例子

use std::collections::HashMap;
let mut a = HashMap::new();
a.insert(1, "a");
a.clear();
assert!(a.is_empty());

4.根据键获取相应的值
使用get()方法获取键相应的值。
如果值不存在,则返回None 。
如果值存在,则返回值的一个引用。

例子

use std::collections::HashMap;
fn main() {
     let mut stateCodes = HashMap::new();
     stateCodes.insert("name","简单教程");
     stateCodes.insert("site","https://www.twle.cn");
     println!("size of map is {}",stateCodes.len());
     println!("{:?}",stateCodes);
     match stateCodes.get(&"name") {
         Some(value)=> {
             println!("Value for key name is {}",value);
          }
          None => {
              println!("nothing found");
          }
     }
}
编译运行结果如下
size of map is 2
{"name": "简单教程", "site": "https://www.twle.cn"}
Value for key name is简单教程

get_mut
实例

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";
    }
}

get_key_value
例子

use std::collections::HashMap;
let mut map = HashMap::new();
map.insert(1, "a");
assert_eq!(map.get_key_value(&1), Some((&1, &"a")));
assert_eq!(map.get_key_value(&2), None);

5.遍历映射表
(1)使用引用

for (book, review) in &book_reviews {
     println!("{book}: \"{review}\"");
}

for (book, review) in &mut book_reviews {
    *review = 0;
     println!("{book}: \"{review}\"");
}

(2)使用迭代器
iter()方法会返回映射表中 键值对的引用组成的无序迭代器。
迭代器元素的类型为 (&'a K, &'a V) 。
实例

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);
    }
}
运行结果:
("color", "red")
("size", "10 m^2")
迭代元素是表示键值对的元组。

iter_mut
例子

use std::collections::HashMap;
let mut map = HashMap::from([
("a", 1),
("b", 2),
("c", 3),
]);
// 更新所有值
for (_, val) in map.iter_mut() {
     *val *= 2;
}

6.是否包含指定的键
contains_key()方法用于判断映射表中是否包含指定的键值对。
如果包含指定的键,那么会返回相应的值的引用,否则返回None 。

例子

use std::collections::HashMap;
fn main() {
     let mut stateCodes = HashMap::new();
     stateCodes.insert("name","简单教程");
     stateCodes.insert("site","https://www.twle.cn");
     stateCodes.insert("slogn","简单教程,简单编程");
     if stateCodes.contains_key(&"name") {
         println!("found key");
     }
}
编译运行结果如下
found key

7.entry
entry方法返回键值对
例子

use std::collections::HashMap;
let mut player_stats = HashMap::new();
fn random_stat_buff() -> u32 {
     42
}
player_stats.entry("health").or_insert(100);     // 没有就插入,有就跳过
player_stats.entry("defence").or_insert_with(random_stat_buff);     //没有就插入,有就跳过
let stat = player_stats.entry("attack").or_insert(100);     //没有就插入,返回值的引用
*stat += random_stat_buff();
player_stats.entry("mana").and_modify(|mana| *mana += 200).or_insert(100);     // 有就加200,没有就插入100
println!("{:?}", player_stats);

9.自定义键类型
派生Eq和Hash。 我们还必须导出PartialEq。
例子

use std::collections::HashMap;
#[derive(Hash, Eq, PartialEq, Debug)]
struct Viking {
     name: String,
     country: String,
}
impl Viking {
     /// 创建一个新的Viking。
     fn new(name: &str, country: &str) -> Viking {
         Viking { name: name.to_string(), country: country.to_string() }
     }
}
// 使用HashMap存储Viking的健康点。
let vikings = HashMap::from([
(Viking::new("Einar", "Norway"), 25),
(Viking::new("Olaf", "Denmark"), 24),
(Viking::new("Harald", "Iceland"), 12),
]);
// 使用派生的实现来打印Viking的状态。
for (viking, health) in &vikings {
     println!("{viking:?} has {health} hp");
}

10.其他
keys
返回一个迭代器,以任意顺序访问所有键。 迭代器元素类型为 &'a K。
例子

use std::collections::HashMap;
let map = HashMap::from([
("a", 1),
("b", 2),
("c", 3),
]);
for key in map.keys() {
     println!("{key}");
}

values
返回一个以任意顺序访问所有值的迭代器。 迭代器元素类型为 &'a V。
例子

use std::collections::HashMap;
let map = HashMap::from([
("a", 1),
("b", 2),
("c", 3),
]);
for val in map.values() {
     println!("{val}");
}

is_empty
如果map不包含任何元素,则返回true。
例子

use std::collections::HashMap;
let mut a = HashMap::new();
assert!(a.is_empty());
a.insert(1, "a");
assert!(!a.is_empty());

三、集合HashSet

HashSet是没有重复值的相同数据类型的值的集合。
Rust语言标准库std::collections中定义了结构体HashSet用于描述集合。

(一)定义集合
1.new()创建一个空集合
语法格式如下

let mut hash_set_name = HashSet::new();

2.可以从数组初始化HashSet:

use std::collections::HashSet;
let viking_names = HashSet::from(["Einar", "Olaf", "Harald"]);

(二)使用集合
1.获取集合的长度len()
len() 方法用于获取集合的长度,也就是集合中元素的个数。

范例

use std::collections::HashSet;
fn main() {
     let mut languages = HashSet::new();
     languages.insert("Python");
     languages.insert("Rust");
     languages.insert("Ruby");
     languages.insert("PHP");
     println!("size of the set is {}",languages.len());
}
编译运行结果如下
size of the set is 4

2.添加元素
insert() 用于插入一个值到集合中,如果集合中已经存在指定的值,则返回 false ,否则返回 true 。

例子

use std::collections::HashSet;
fn main() {
     let mut languages = HashSet::new();
     languages.insert("Python");
     languages.insert("Rust");
     languages.insert("Ruby");
     languages.insert("PHP");
     languages.insert("Rust"); // 插入失败但不会引发异常
     println!("{:?}",languages);
}
编译运行结果如下
{"Python", "PHP", "Rust", "Ruby"}

3.删除集合元素
remove() 方法用于从集合中删除指定的值。
删除之前如果值 value 存在于集合中则返回 true ,如果不存在则返回 false 。

例子

use std::collections::HashSet;
fn main() {
     let mut languages = HashSet::new();
     languages.insert("Python");
     languages.insert("Rust");
     languages.insert("Ruby");
     println!("length of the Hashset: {}",languages.len());
     languages.remove(&"Kannan");
     println!("length of the Hashset after remove() : {}",languages.len());
}
编译运行结果如下
length of the Hashset: 3
length of the Hashset after remove() : 3

clear
删除所有值。
例子

use std::collections::HashSet;
let mut v = HashSet::new();
v.insert(1);
v.clear();
assert!(v.is_empty());

4.获取元素
get() 方法用于获取集合中指定值的一个引用。
如果值 value 存在于集合中则返回集合中的相应值的一个引用,否则返回 None 。

例子

use std::collections::HashSet;
fn main() {
     let mut languages = HashSet::new();
     languages.insert("Python");
     languages.insert("Rust");
     languages.insert("Ruby");
     languages.insert("PHP");
     match languages.get(&"Rust"){
         Some(value)=>{
              println!("found {}",value);
          }
          None =>{
              println!("not found");
          }
     }
     println!("{:?}",languages);
}
编译运行结果如下
found Rust
{"Python", "Ruby", "PHP", "Rust"}

take
删除并返回集合中等于给定值的值 (如果有)。
该值可以是集合值类型的任何借用形式,但是借用形式上的Hash和Eq必须与值类型的那些匹配。
例子

use std::collections::HashSet;
let mut set = HashSet::from([1, 2, 3]);
assert_eq!(set.take(&2), Some(2));
assert_eq!(set.take(&2), None);

5.遍历集合
(1)使用引用

for book in &books {
     println!("{book}");
}

(2)使用迭代器
iter()方法用于返回集合中所有元素组成的无序迭代器。
迭代器元素的顺序是无序的,毫无规则的。而且每次调用iter() 返回的元素顺序都可能不一样。

例子

use std::collections::HashSet;
fn main() {
     let mut languages = HashSet::new();
     languages.insert("Python");
     languages.insert("Rust");
     languages.insert("Ruby");
     languages.insert("PHP");
     for language in languages.iter() {
         println!("{}",language);
     }
}
编译运行结果如下
PHP
Python
Rust
Ruby

6.判断集合是否包含某个值
contains() 方法用于判断集合是否包含指定的值。
如果值 value 存在于集合中则返回 true ,否则返回 false 。

例子

use std::collections::HashSet;
fn main() {
     let mut languages = HashSet::new();
     languages.insert("Python");
     languages.insert("Rust");
     languages.insert("Ruby");
     if languages.contains(&"Rust") {
         println!("found language");
     }
}
编译运行结果如下
found language

7.自定义类型
派生Eq和Hash。我们还必须导出PartialEq,这将在Eq中隐含在future中。

use std::collections::HashSet;
#[derive(Hash, Eq, PartialEq, Debug)]
struct Viking {
     name: String,
     power: usize,
}
let mut vikings = HashSet::new();
vikings.insert(Viking { name: "Einar".to_string(), power: 9 });
vikings.insert(Viking { name: "Einar".to_string(), power: 9 });
vikings.insert(Viking { name: "Olaf".to_string(), power: 4 });
vikings.insert(Viking { name: "Harald".to_string(), power: 8 });
for x in &vikings {
     println!("{x:?}");
}

8.其他
is_empty
如果集合不包含任何元素,则返回true。
例子

use std::collections::HashSet;
let mut v = HashSet::new();
assert!(v.is_empty());
v.insert(1);
assert!(!v.is_empty());

union
访问表示并集的值,即self或other中的所有值,没有重复项。
例子

use std::collections::HashSet;
let a = HashSet::from([1, 2, 3]);
let b = HashSet::from([4, 2, 3, 4]);
// 以任意顺序打印1、2、3、4。
for x in a.union(&b) {
println!("{x}");
}
let union: HashSet<_> = a.union(&b).collect();
assert_eq!(union, [1, 2, 3, 4].iter().collect());

intersection
访问表示相交的值,即self和other中的值。
当self和other中存在相等的元素时,生成的Intersection可能会引用其中一个。 如果T包含未通过其Eq实现进行比较的字段,并且可能在两组T的两个相等副本之间保持不同的值,则这可能是相关的。
例子

use std::collections::HashSet;
let a = HashSet::from([1, 2, 3]);
let b = HashSet::from([4, 2, 3, 4]);
// 以任意顺序打印2,3。
for x in a.intersection(&b) {
println!("{x}");
}
let intersection: HashSet<_> = a.intersection(&b).collect();
assert_eq!(intersection, [2, 3].iter().collect());

is_subset
如果集合是另一个集合的子集,则返回true,即other至少包含self中的所有值。
例子

use std::collections::HashSet;
let sup = HashSet::from([1, 2, 3]);
let mut set = HashSet::new();
assert_eq!(set.is_subset(&sup), true);
set.insert(2);
assert_eq!(set.is_subset(&sup), true);
set.insert(4);
assert_eq!(set.is_subset(&sup), false);

is_superset
如果集合是另一个集合的超集,则返回true,即self至少包含other中的所有值。
例子文章来源地址https://uudwc.com/A/Oq6y2

use std::collections::HashSet;
let sub = HashSet::from([1, 2]);
let mut set = HashSet::new();
assert_eq!(set.is_superset(&sub), false);
set.insert(0);
set.insert(1);
assert_eq!(set.is_superset(&sub), false);
set.insert(2);
assert_eq!(set.is_superset(&sub), true);

原文地址:https://blog.csdn.net/inxunxun/article/details/132998193

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请联系站长进行投诉反馈,一经查实,立即删除!

h
上一篇 2023年09月25日 13:35
信创办公–基于WPS的EXCEL最佳实践系列 (限制可录入内容)
下一篇 2023年09月25日 13:36