Rust学习笔记 (七) common collections

#ProgrammingLanguage/Rust

大多数数据类型代表一种特定的值,但是collections可以包含不同的值。

常用的三种collections:

creating a new vector

let v: Vec<i32> = Vec::new();

let v = vec![1, 2, 3]; //vec! 是宏

因为vector是一个连续的链表,添加元素,只能通过push操作。

let mut v = Vec::new();

v.push(5);
v.push(6);
v.push(7);
v.push(8);

读取一个vector

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

let third: &i32 = &v[2]; //序号0,1,2

let third: Option<&i32> = v.get(2);

规定在同一范围内不能有可变且不变的引用。

let mut v = vec![1, 2, 3, 4, 5];
let first = &v[0];
v.push(6);

所以上述代码,因为 first 这个引用是不可变的,因此最后一句报错,无法执行。

遍历vector

let v = vec![100, 32, 57]; 
for i in &v {
	println!("{}", i); 
}

let mut v = vec![100, 32, 57]; 
for i in &mut v {
	*i += 50; 
}

using an enum to store multiple types 可以定义一个枚举,其变量包含不同的值类型,然后所有枚举变量被视为相同的类型:枚举变量。 然后我们,就可以创建一个vector来包含这些枚举变量。 此举的目的就是为了,让vector可以每个元素的实际变量类型不同。

enum SpreadsheetCell {
  Int(i32),
	Float(f64),
  Text(String),
}
let row = vec![
	SpreadsheetCell::Int(3),
  SpreadsheetCell::Text(String::from("blue")),
  SpreadsheetCell::Float(10.12),
];

storing UTF-8 encoded text with strings

let mut s = String::new();

let data = "initial contents"; 

let s = data.to_string();

// the method also works on a literal directly: 
let s = "initial contents".to_string();

let s = String::from("initial contents");

修改更新string

let mut s = String::from("foo"); 
s.push_str("bar");

//单个字符使用push
let mut s = String::from("lo"); 
s.push('l');

let s1 = String::from("Hello, ");
let s2 = String::from("world!");
let s3 = s1 + &s2; // note s1 has been moved here and can no longer be used

如果你要把多个字符串连接起来,+操作会比较沉重,效率较低。 建议使用format!宏。

let s1 = String::from("tic"); 
let s2 = String::from("tac"); 
let s3 = String::from("toe");

let s = format!("{}-{}-{}", s1, s2, s3);

使用format,让代码更易阅读,并且不会获取所有权。

indexing into strings string 是一个 Vec的封装。

Bytes and Scalar Values and Grapheme Clusters! Rust不允许我们索引到String中以获取字符的最后一个原因是,索引操作总是需要恒定的时间(O(1))。

分割字符串

let hello = "􏱤􏱥􏱦􏱧􏱨abcdefg􏱣􏱤􏱥􏱦􏱧􏱨􏱩􏱧􏱪􏱫􏱩􏱬"; 
let s = &hello[0..4];

迭代获取字符

for c in "abcdefghi".chars() {
	println!("{}" , c);
}

for c in "abcdefghi".bytes() {
	println!("{}" , c);
}

hash maps

use std::collections::HashMap; 
let mut scores = HashMap::new();
scores.insert(String::from("Blue"), 10); scores.insert(String::from("Yellow"), 50);


let teams = vec![String::from("Blue"),String::from("Yellow")]; 
let initial_scores = vec![10, 50];
let scores: HashMap<_, _> = teams.iter().zip(initial_scores.iter()).collect();

哈希表的所有权:

use std::collections::HashMap;
let field_name = String::from("Favorite color"); 
let field_value = String::from("Blue");
let mut map = HashMap::new();
map.insert(field_name, field_value);
// field_name and field_value are invalid at this point, try using them and see what compiler error you get!

accessing values in a hash map

use std::collections::HashMap; 
let mut scores = HashMap::new();
scores.insert(String::from("Blue"), 10); scores.insert(String::from("Yellow"), 50);
let team_name = String::from("Blue"); 
let score = scores.get(&team_name);

for (key, value) in &scores { 
	println!("{}: {}", key, value);
}

overwriting a value

use std::collections::HashMap;
let mut scores = HashMap::new();
scores.insert(String::from("Blue"), 10); scores.insert(String::from("Blue"), 25);
println!("{:?}", scores);

only inserting a value if the key has no value

use std::collections::HashMap;
let mut scores = HashMap::new(); scores.insert(String::from("Blue"), 10);
scores.entry(String::from("Yellow")).or_insert(50); scores.entry(String::from("Blue")).or_insert(50);
println!("{:?}", scores);

update a value based on the old value

use std::collections::HashMap;
let text = "hello world wonderful world"; 
let mut map = HashMap::new();
for word in text.split_whitespace() {
	let count = map.entry(word).or_insert(0); 
	*count += 1;
}
println!("{:?}", map);