vec基础
具体细节在代码中,注意引用的技巧,一般使用get()
获取元素,这样如果越过边界,返回的是None
。
fn main() {
let v = vec![1, 2, 3, 4, 5];
let x = v.get(2); //
match x {
Some(3) => println!("OK"),
None => println!("No"),
_ => println!("Nothing"),
}
for i in &v { // 使用引用的方式遍历,去掉&是基于值的,每个都要复制一遍
println!("{}", i);
}
let mut v1 = vec![1, 2, 3, 4, 5];
for i in &mut v1 {
*i += 10; // 必须要解引用
}
for i in &v1 {
println!("{}", i);
}
// 通过枚举绑定的形式,可以让一个vec存储多个类型的值,使用match的方式获取
enum Cell {
Int(i32),
Float(f64),
Text(String),
}
let mut rows: Vec<Cell> = Vec::new();
rows.push(Cell::Int(10));
rows.push(Cell::Float(1.35));
rows.push(Cell::Text(String::from("hello world !")));
for i in & rows {
match i {
Cell::Int(val) => println!("{}", val),
Cell::Float(val) => println!("{}", val),
Cell::Text(val) => println!("{}", val),
}
}
}
注意一个易错点,vec
当元素不够的时候,会重新申请内存,然后把之前的元素复制到新内存中;这样,如果之前有引用指向某个元素,那么会报错。错误代码实例:
fn main() {
let mut v = vec![3; 3];
let r = &v[0];
v.push(1); // 重新申请内存,导致下一句报错
println!("r = {}", r);
}
字符串类型
fn main() {
// 初始化的几个方式
let mut s0 = String::new();
let data = "initial contents";
let s1 = data.to_string();
let s2 = "hello world !".to_string();
let s3 = String::from("hello world !");
// 拼接的方式
let s4 = "hello".to_string();
let s5 = String::from("world");
let s6 = String::from("!");
// +拼接只是针对&str而言的
let s7 = s4 + " " + &s5 + " " + &s6; // 此时的s4已经无效了
println!("s7 = {}", s7);
let s4 = "hello".to_string(); // 重新定义s4
let s8 = format!("{} {} {}", s4, s5, s6); // format拼接,都是有效的
println!("s8 = {}", s8);
}
字符串不能基于下标遍历,因为不同字符的编码是不一样的,rust直接在语言层面就禁止了。遍历只能通过for
循环的形式进行,代码实例:
fn main() {
let s = String::from("hello, 我来自中国,Indian नमस्त");
for c in s.chars() { // 遍历每个实际的字符
println!("{}", c);
}
for c in s.bytes() { // 遍历每个编码
println!("{}", c);
}
}
map类型
这里仅仅介绍HashMap
的结构,基于哈希算法的。先给出几个基本的操作:
use std::collections::HashMap;
fn main() {
// 新建
let mut nums = HashMap::new();
// 简单插入
nums.insert(1, String::from("one"));
nums.insert(2, String::from("two"));
nums.insert(3, String::from("three"));
nums.insert(4, String::from("four"));
// 删除
nums.remove(&4);
// 基于引用的遍历
for (k, v) in &mut nums {
println!("key = {}, value = {}", k, v);
}
// 基于get获取元素
let v = nums.get(&1);
match v { // 必须使用这种方式获取对应的值
Some(val) => println!("{}", val),
None => println!("No key !"),
}
}
注意HashMap所有权的问题,一旦一个元素insert进入容器,那么对应的所有权就归容器所有了
还有一个基于vec
的collect
方法的构造方式,在这里给出一个代码实例:
use std::collections::HashMap;
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 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);