当前位置:   article > 正文

Rust的集合_rust collect

rust collect

一、Rust中的集合

集合这个概念和数学的本质是一样的,就是一群类似的数据放到一起。在Rust中主要有三种集合:
1、字符串
这个应该不用过多解释,就是一串字符组合在一起。
2、Vec
学过c++的STL的同学可能一下子就会明白,一个动态数组,平坦空间上的。
3、HashMap
这个其实是两个数据结构Hash和Map组合在一起。

二、集合的应用

1、Vec的应用
vec是一个动态增删数据的数组,平均的时间复杂度是O(1)。换句话说,它可以随机的访问数据内容;同时,对首尾的写操作也是O(1)。看下面的例程:

//new方式声明
let mut v1: Vec<i32> = Vec::new();
//宏方式
let v: Vec<i32> = vec![];
// 以下语句相当于:
// let mut temp = Vec::new();
// temp.push(1);
// temp.push(2);
// temp.push(3);
// let v = temp;
let v = vec![1, 2, 3];
let v = vec![0; 10]; //注意分号,这句话声明了一个 内容为10个0的动态数组
//迭代器声明
let v: Vec<_> = (1..5).collect();
//直接访问
let a = vec![1, 2, 3];
assert_eq!(a[1usize], 2);

//安全访问
let v =vec![1, 2, 3];
assert_eq!(v.get(1), Some(&2));
assert_eq!(v.get(3), None);

//迭代器访问
let v = vec![1, 2, 3];
for i in &v { .. } // 获得引用
for i in &mut v { .. } // 获得可变引用
for i in v { .. } // 获得所有权,注意此时Vec的属主将会被转移!!
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

再看一个例程:

use std::time;
fn push_1m(v: &mut Vec<usize>, total: usize) {
    let e = time::SystemTime::now();
    for i in 1..total {
        v.push(i);
    }
    let ed = time::SystemTime::now();
    println!("time spend: {:?}", ed.duration_since(e).unwrap());
}
fn main() {
    let mut v: Vec<usize> = vec![];
    push_1m(&mut v, 5_000_000);
    let mut v: Vec<usize> = vec![];
    v.reserve(5_000_000);
    push_1m(&mut v, 5_000_000);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

这个vec的缺点和STL中的没啥不同,都是内存的冗余消耗和复制的时间消耗。

2、HashMap
这个集合在td::collections下,有一个o(1)的查询方法。它要求Key必须是可比较的,注意,如果自定义一个Key,需要处理一下。

use std::collections::HashMap;
// 声明
let mut come_from = HashMap::new();
// 插入
come_from.insert("WaySLOG", "HeBei");
come_from.insert("Marisa", "U.S.");
come_from.insert("Mike", "HuoGuo");
// 查找key
if !come_from.contains_key("elton") {
    println!("Oh, 我们查到了{}个人,但是可怜的Elton猫还是无家可归", come_from.len());
}
// 根据key删除元素
come_from.remove("Mike");
println!("Mike猫的家乡不是火锅!不是火锅!不是火锅!虽然好吃!");
// 利用get的返回判断元素是否存在
let who = ["MoGu", "Marisa"];
for person in &who {
    match come_from.get(person) {
        Some(location) => println!("{} 来自: {}", person, location),
        None => println!("{} 也无家可归啊.", person),
    }
}
// 遍历输出
println!("那么,所有人呢?");
for (name, location) in &come_from {
    println!("{}来自: {}", name, location);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

对存在Key的处理,Rust提供了entry这种处理方式:

use std::collections::HashMap;
let mut letters = HashMap::new();
for ch in "a short treatise on fungi".chars() {
    let counter = letters.entry(ch).or_insert(0);
    *counter += 1;
}
assert_eq!(letters[&'s'], 2);
assert_eq!(letters[&'t'], 3);
assert_eq!(letters[&'u'], 1);
assert_eq!(letters.get(&'y'), None);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

它的优势就在于,编程者不用再写一个丑陋的判断语句判断是否此数据已经存在于HashMap中,而自动交给entry().or_insert来处理。

3、字符串
字符串几乎所有的语言都处理,只有C清高对些不屑一顾。rust中字符串默认是以UTF-8编码的。

let mut s = String::new();
let data = "my strings";
let s = data.to_string();

// 直接赋值:
let s = "my strings".to_string();
//from赋值
let ss = String::from("my strings");
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

字符串的几乎所有想到的操作Rust中都提供了,包括slice:


//追加字符串
fn main() {
let mut s = String::from("add ");
s.push_str(" one");
}

//拼接字符串
fn main() {
let s1 = String::from("Hello, ");
let s2 = String::from("world!");
let s3 = s1 + &s2; // 注意 s1 被移动了,不能继续使用
}
//拼接字符串2
fn main() {
let s11 = String::from("ddc");
let s12 = String::from("erc");
let s13 = String::from("ghu");

let s = format!("{}-{}-{}", s11, s12, s13);
}
//字符串的slice
fn main() {
let hello = "qswertyuihu";

let s = &hello[0..4];
//let s = &hello[0..1] ;//panic 一定要小心
}
//遍历
fn main() {
for c in "asdfgh".chars() {
    println!("{}", c);
}

for b in "asdfgh".bytes() {
    println!("{}", b);
}
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

有所不同的是,在Rust中不允许索引字符串,比如像c++中直接通过下标或者指针来访问具体索引上的字符串,是编译无法通过的。知易行难啊,不容易。

  • 代码主要来自《Rust Primer》

三、总结

对于类似于STL的这种集合的操作,原则上是越多越方便,越简单越方便。同时,这些集合的底层实现和跨平台的效率却更是体现了Rust语言本身的开发者的能力。一个好的语言,一定会有一个尽量兼顾各方的库和其它结构,这既是一个对上层友好的优点,也是对语言开发者本身不友好的缺点,而且,这还可能造成其在某个特点平台或者特定场合下的效率的不够高。这也是所有这种框架和库的本身的一种无奈,既想要面面具到,又无法面面具到。其实在前面就提到过,Rust本身在这方面其实就很有果决的勇气,删除了很多东西,这也是Rust在社区广受好评的一个重要因素。
正所谓,有得就有失,有失就有得。努力吧,归来的少年!
在这里插入图片描述

本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/951186
推荐阅读
相关标签
  

闽ICP备14008679号