Rust中向量的學習筆記
概述
在Rust語言中,向量(Vector)是一種動態(tài)數(shù)組類型,可以存儲相同類型的元素,并且可以在運行時改變大小。向量是Rust標準庫中的一部分,位于std::vec模塊中。向量是一個非常靈活和強大的數(shù)據(jù)結構,可以方便地用于各種場景,包括:存儲數(shù)據(jù)、處理集合、構建動態(tài)數(shù)組等。
向量的創(chuàng)建
向量類型由標準庫中的Vec<T>結構體實現(xiàn),這里的T是類型參數(shù),代表向量能夠存儲任何類型的單個值,但所有元素必須是同一類型。Rust的向量是在堆上分配的,這意味著當我們創(chuàng)建一個向量時,它會在堆上分配內存,而不是在棧上。因此,當向量超出作用域時,Rust會自動釋放其占用的內存,防止內存泄漏。
在Rust中,創(chuàng)建向量主要有以下4種方法。
1、使用Vec::new創(chuàng)建空向量。
let mut vec_number: Vec<i32> = Vec::new();
2、使用vec!宏創(chuàng)建帶有初始值的向量。
fn main() {
// 創(chuàng)建一個整數(shù)向量
let vec_number: Vec<i32> = vec![66, 99, 100];
println!("{:?}", vec_number);
// 創(chuàng)建一個字符串向量
let vec_str: Vec<String> = vec!["CSDN".to_string(), "GitHub".to_string()];
println!("{:?}", vec_str);
}3、使用vec!宏創(chuàng)建指定長度,并初始化所有元素為相同值的向量。
fn main() {
let vec_number: Vec<i32> = vec![0; 5];
// 輸出:[0, 0, 0, 0, 0]
println!("{:?}", vec_number);
}4、使用Vec::with_capacity創(chuàng)建具有特定容量,但長度為0的向量。
fn main() {
// 創(chuàng)建一個初始為空,但足夠存儲5個整型元素的向量
let mut vec_number: Vec<i32> = Vec::with_capacity(5);
// 輸出:[]
println!("{:?}", vec_number);
}向量的訪問
訪問向量的元素,可以通過索引或迭代器進行。
1、通過索引訪問。注意:Rust中的索引是基于0的,即第一個元素的索引是0,最后一個元素的索引是向量長度減1。在Rust中使用索引訪問元素,沒有運行時邊界檢查。如果索引超過邊界,會導致程序崩潰。為了更安全地使用索引訪問,避免因索引越界引發(fā)崩潰,可以使用get()方法或get_mut()方法,它返回一個Option<&T>或Option<&mut T>。
fn main() {
let mut vec_number = vec![66, 99, 100];
// 訪問第一個元素,輸出:66
println!("{}", vec_number[0]);
// 修改第二個元素
vec_number[2] = 88;
// 安全訪問,當索引不存在時,不會panic
if let Some(value) = vec_number.get(2) {
// 輸出:88
println!("{}", value);
} else {
println!("out of bounds");
}
// 對可變引用的安全訪問,可修改向量中的元素
let mut vec_mut = vec![1, 2, 3];
if let Some(value) = vec_mut.get_mut(1) {
*value = 1024;
}
// 輸出:[1, 1024, 3]
println!("{:?}", vec_mut);
// 獲取向量的長度,輸出:3
println!("{}", vec_mut.len());
// 清空向量,并判斷向量是否為空
vec_mut.clear();
if vec_mut.is_empty() {
println!("empty");
} else {
println!("not empty");
}
}2、通過迭代器訪問。迭代器(Iterator)是訪問向量元素的一種安全、高效且靈活的方式。通過迭代器可以遍歷向量中的所有元素,并對它們執(zhí)行操作,而無需關心具體的索引。iter()方法用于獲取只讀迭代器,iter_mut()方法用于獲取可寫迭代器,into_iter()方法用于消耗向量并迭代。
fn main() {
let mut vec_str = vec!["CSDN", "GitHub", "Gitee"];
// 使用for循環(huán)遍歷向量的所有元素
for s in &vec_str {
println!("{}", s);
}
// 使用iter()顯式獲取迭代器
for s in vec_str.iter() {
println!("{}", s);
}
// 若要修改元素,需使用iter_mut()獲得可變引用迭代器
for s in vec_str.iter_mut() {
if s.starts_with("C") {
*s = "Rust";
}
}
println!("{:?}", vec_str);
for s in vec_str.into_iter() {
println!("{}", s);
}
// 到這里時,vec_str不再有效,因為它已經被消耗掉了
// println!("{:?}", vec_str);
}向量的修改
1、添加、移除元素。使用push方法可以將元素添加到向量的末尾,使用pop方法可以從向量的末尾移除元素并返回該元素。
fn main() {
let mut vec_number = vec![10, 20];
vec_number.push(66);
// 輸出:[10, 20, 66]
println!("{:?}", vec_number);
let last_number = vec_number.pop();
// 輸出:66
if let Some(value) = last_number {
println!("{}", value);
} else {
println!("no data");
}
// 輸出:[10, 20]
println!("{:?}", vec_number);
}2、插入、刪除元素。insert)方法用于將元素插入到指定索引位置,原有位置及之后的元素都會右移。remove()方法用于刪除并返回指定索引位置的元素,之后的元素會左移填補空位。注意:插入和刪除操作可能導致向量內部需要重新分配內存以適應大小的變化,這可能涉及到元素的移動;因此,對于大型數(shù)據(jù)集或性能敏感的應用,這些操作可能會有較高的時間開銷。
fn main() {
let mut vec_number = vec![10, 20];
// 插入元素
vec_number.insert(1, 66);
// 輸出:[10, 66, 20]
println!("{:?}", vec_number);
// 刪除元素
vec_number.remove(0);
// 輸出:[66, 20]
println!("{:?}", vec_number);
}向量的切片
Rust的向量支持切片操作,這意味著,我們可以獲取向量的一部分作為新的向量。切片是通過指定起始索引和結束索引來創(chuàng)建的,注意:包括起始索引的元素,但不包括結束索引的元素。
fn main() {
let mut vec_number = vec![10, 20, 30, 40, 50];
// 獲取一個切片,從索引2到4(不包括4)
let slice = &mut vec_number[2..4];
// 輸出:[30, 40]
println!("{:?}", slice);
// 修改切片中的元素
for item in slice.iter_mut() {
*item *= 2;
}
// 輸出:[60, 80]
println!("{:?}", slice);
}向量的排序
Rust的向量可以通過sort()方法或sort_unstable()來進行排序,還可以通過sort_by()方法或sort_unstable_by()方法根據(jù)自定義的比較邏輯來進行排序。sort()方法是穩(wěn)定的排序算法,即相同元素的相對順序不會改變。sort_unstable()方法是不穩(wěn)定的排序算法,意味著相同的元素可能會改變相對順序,但總體上會按照給定的排序規(guī)則排序。
fn main() {
let mut vec_number = vec![7, 88, 12, 36, 50];
// 默認為升序排序
vec_number.sort_unstable();
// 輸出:[7, 12, 36, 50, 88]
println!("{:?}", vec_number);
// 顯式指定排序規(guī)則,仍然是升序
vec_number.sort_by(|a, b| a.cmp(b));
// 輸出: [7, 12, 36, 50, 88]
println!("{:?}", vec_number);
// 若要降序排序,反轉比較結果
vec_number.sort_unstable_by(|a, b| b.cmp(a));
// 輸出: [88, 50, 36, 12, 7]
println!("{:?}", vec_number);
}向量的擴展和收縮
在Rust中,向量提供了幾種方法來管理其容量和大小。容量是向量在內存中為元素預留的空間大小,而大小則是向量當前實際包含的元素數(shù)量。當添加元素到向量時,如果當前容量不足,向量可能會自動增長其容量。但這并不意味著當我們刪除元素時,向量會自動縮小其容量。
以下是向量中用于管理容量的幾個方法。
1、resize方法用于改變容量的大小。如果新的大小大于當前大小,向量會在末尾添加默認值(對于整數(shù)類型,通常是0;對于其他類型,則依賴于其默認構造函數(shù))。如果新的大小小于當前大小,向量會丟棄末尾的多余元素。
fn main() {
let mut vec_number = vec![10, 20, 30];
// 向量為[10, 20, 30, 0, 0],大小為5,容量可能增長以容納更多元素
vec_number.resize(5, 0);
println!("{:?}", vec_number);
// 向量為[10, 20],大小為2,但容量可能仍然大于2
vec_number.resize(2, 0);
println!("{:?}", vec_number);
}2、reserve方法用于確保向量至少有足夠的容量來存儲指定數(shù)量的元素,而不會重新分配。如果當前容量小于所需容量,向量會分配更多內存,這不會改變向量的大小。
fn main() {
let mut vec_number = vec![10, 20, 30];
// 確保vec至少有20的容量,但不改變其大小和內容
vec_number.reserve(20);
// 輸出:[10, 20, 30]
println!("{:?}", vec_number);
}3、shrink_to_fit方法嘗試將向量的容量減少到與其大小相同。這通常在我們確定不再需要額外容量,并且希望減少內存使用時很有效。注意:這個方法并不保證一定能減少容量,某些情況下,出于性能或實現(xiàn)的原因,向量可能會保留一些額外的容量。
fn main() {
let mut vec_number = vec![10, 20, 30];
// 將容量增加到10
vec_number.reserve(10);
// 刪除一個元素,現(xiàn)在大小是2,但容量可能仍然是10
vec_number.pop();
// 嘗試將容量減少到2
vec_number.shrink_to_fit();
println!("{}", vec_number.capacity());
}注意:在使用上述這些方法時,我們應該考慮性能開銷和內存使用之間的權衡。頻繁地調整向量的容量可能會導致不必要的性能開銷,因此在確定確實需要調整容量時,才應該使用這些方法。
向量的連接和合并
在Rust中,如果想要連接或合并多個集合,可以使用extend方法,或者利用迭代器的collect方法。在下面的示例代碼中,我們使用extend方法后,vec2被轉移了所有權,已經無效了。collect方法通常與迭代器一起使用,用于將迭代器中的元素收集到一個集合中。
fn main() {
let mut vec1 = vec![1, 2, 3];
let vec2 = vec![4, 5, 6];
// 將vec2的內容添加到vec1末尾
vec1.extend(vec2);
// 輸出:[1, 2, 3, 4, 5, 6]
println!("{:?}", vec1);
// vec2被extend函數(shù)轉移了所有權,到這里時無效了
// println!("{:?}", vec2);
// 創(chuàng)建一個新的向量來包含兩個向量的內容
let vec3 = vec![1, 2, 3];
let vec4 = vec![4, 5, 6];
let vec5: Vec<i32> = vec3.into_iter().chain(vec4).collect();
// 輸出:[1, 2, 3, 4, 5, 6]
println!("{:?}", vec5);
}到此這篇關于Rust中向量的學習筆記的文章就介紹到這了,更多相關Rust 向量內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Rust動態(tài)調用字符串定義的Rhai函數(shù)方式
Rust中使用Rhai動態(tài)調用字符串定義的函數(shù),通過eval_expression_with_scope實現(xiàn),但參數(shù)傳遞和函數(shù)名處理有局限性,使用FnCall功能更健壯,但更復雜,總結提供了更通用的方法,但需要處理更多錯誤情況2025-02-02
解讀Rust的Rc<T>:實現(xiàn)多所有權的智能指針方式
Rc<T> 是 Rust 中用于多所有權的引用計數(shù)類型,通過增加引用計數(shù)來管理共享數(shù)據(jù),只有當最后一個引用離開作用域時,數(shù)據(jù)才會被釋放,Rc<T> 適用于單線程環(huán)境,并且只允許不可變共享數(shù)據(jù);需要可變共享時應考慮使用 RefCell<T> 或其他解決方案2025-02-02

