English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Collections (Collection) are the most common form of data storage in data structures, and the Rust standard library provides a rich set of collection types to help developers handle operations on data structures.
Vectors (Vector) are a single data structure that stores multiple values, and this structure stores values of the same type linearly in memory.
Vectors are linear lists, and in Rust, they are represented as Vec<T>.
The usage of vectors is similar to that of lists, and we can create a vector of a specified type in this way:
let vector: Vec<i32>= Vec::new(); // Create a type of i32 an empty vector let vector = vec![1, 2, 4, 8]; // Vector creation through array
We often use the append operation with linear lists, but the append operation and the push operation of a stack are essentially the same, so the vector only has a push method to append a single element:
fn main() { let mut vector = vec![1, 2, 4, 8]; vector.push(16); vector.push(32); vector.push(64); println!("{:?}", vector); }
Running Result:
[1, 2, 4, 8, 16, 32, 64]
The append method is used to concatenate one vector to the end of another vector:
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); }
Running Result:
[1, 2, 4, 8, 16, 32, 64]
The get method is used to retrieve values from the vector:
fn main() { Let1, 2, 4, 8]; println!("{}", match v.get(0) { Some(value) => value.to_string(), None => "None".to_string() }); }
Running Result:
1
Because the length of the vector cannot be logically inferred, the get method cannot guarantee that a value will always be obtained, so the return value of the get method is an Option enum, which may be empty.
This is a safe way to access values, but it is a bit麻烦 to write. If you can ensure that the index of the value does not exceed the range of vector index values, you can also use array access syntax:
fn main() { Let1, 2, 4, 8]; println!("{}", v[1]); }
Running Result:
2
But if we try to access v[4], then the vector will return an error.
Traverse the vector:
fn main() { Let100, 32, 57]; For Println("{}", i); } }
Running Result:
100 32 57
If you need to change the value of a variable during the traversal process:
fn main() { Let100, 32, 57]; For *i += 50; } }
String (String) has been used a lot in this chapter, so many methods are already familiar to readers. This chapter mainly introduces string methods and UTF-8 Properties.
New string:
Let
Basic type conversion to string:
Let 1.to_string(); // Integer to string Let 1.3.to_string(); // Float to string Let // String slicing to string
Contain UTF-8 Character strings:
Let Let Let Let Let Let Let Let Let Let Let
Let
String concatenation: s.push_str("oob"); // Appending string slices s.push('!'); // Appending characters
Using + Concatenating strings:
let s1 = let s2 = let s3 =1 + &s2;
=
let s1 = String::from("tic"); let s2 = String::from("tac"); let s3 = String::from("toe"); This syntax can also include string slicing:1 + "-" + &s2 + "-" + &s3;
Use the format! macro:}
let s1 = String::from("tic"); let s2 = String::from("tac"); let s3 = String::from("toe"); let s = format!("{}",-{}-{}", s1, s2, s3);
String length:
let s = "hello"; let len = s.len();
Here the value of len is 5.
let s = "你好"; let len = s.len();
Here the value of len is 6. Because Chinese is UTF-8 encoded, each character is long 3 bytes, so the length is6. But Rust supports UTF-8 character objects, so if you want to count the number of characters, you can first take the string as a character set:
let s = "hello Chinese"; let len = s.chars().count();
Here the value of len is 7, because there are a total of 7 The speed of counting characters is much slower than the speed of counting the length.
Traverse the string:
fn main() { let s = String::from("hello Chinese"); for c in s.chars() { println!("{}", c); } }
Running Result:
h e l l o 中 文
Extract a single character from a string:
fn main() { let s = String::from("EN Chinese"); let a = s.chars().nth(2); println!("{:?}", a); }
Running Result:
Some('中')
Note: The nth function is a method to extract a value from an iterator, please do not use it in this way during traversal! Because UTF-8 The length of each character may not be equal!
If you want to extract a substring of a string:
fn main() { let s = String::from("EN Chinese"); let sub = &s[0..2]; println!("{}", sub); }
Running Result:
EN
However, please note that this usage may split a UTF-8 Characters! This will cause an error:
fn main() { let s = String::from("EN Chinese"); let sub = &s[0..3]; println!("{}", sub); }
Running Result:
thread 'main' panicked at 'byte index 3 is not a character boundary; it is inside '中' (bytes 2..5) of `EN Chinese`, src\libcore\str\mod.rs:2069:5 note: run with `RUST_BACKTRACE=1`1environment variable to display a backtrace.
Mapping tables (Map) are widely used in other languages. The most commonly used is the key-value hash map (Hash Map).
Create a new hash table value map:
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()); }
Note: There is no declaration of the generic type of the hash table here because of Rust's automatic type judgment mechanism.
Running Result:
red
The insert method and the get method are the two most commonly used methods of the map.
The map supports iterators:
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); } }
Running Result:
("color", "red") ("size", ""10 m^2)
Iterating elements are tuples representing key-value pairs.
Rust's map is a very convenient data structure. When using the insert method to add a new key-value pair, if the same key already exists, it will directly overwrite the corresponding value. If you want to "safely insert", that is, to perform the insertion action only when confirming that the current key does not exist, you can do so:
map.entry("color").or_insert("red");
This sentence means that if there is no key-value pair with the key "color", add it and set the value to "red", otherwise skip.
If you want to directly modify the corresponding value when you have already determined that there is a certain key, there is a faster way:
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"; } }