切片
切片是 Rust 中提供的一種不持有所有權的資料型別,它是對某些型別(String,Array...)特定位置的引用。
- 在 Rust 中,字串的字面值就是切片型別,是對二進位制程式特定位置值的一個引用,並且是不可變引用
- 切片型別的符號使用 &str 表示
接下來我們看一下如何建立一個切片
// 1.使用字面值建立切片
let slice = "haha";
// 2.使用 range 對 String 進行切片
let s = String::from("hello world");
let sclice_s = &s[0..5]; // "hello"
// 如果是從開頭到結尾進行切片,則可以簡寫
let sclice_s_all = &s[..]; // "hello world"
為什麼要使用切片
對於初學的同學可能會有這樣一個疑問,為什麼要使用切片,使用切片是為了解決什麼問題?要搞明白這些問題,我們首先應該瞭解一些應用場景,才能有助於後續的分析。假設現在我們要設計這樣一個函式,其功能是提取一個字串中首個空格前的所有字元,沒有空格則返回整個字串,如("hello world" 提取出 "hello"),但現在我們不能使用切片,只能考慮獲取關鍵位置的索引
- 從一個字串中匹配第一個出現的空格,並返回其索引
- 如果沒有匹配到空格,則返回字串的長度
接下來我們看 Rust 的實現
fn main() {
let str = String::from("hello world");
let index = get_space_index(&str);
println!("index is {}", index); // index is 5
}
fn get_space_index(s: &String) -> usize {
// 將字串轉為字元陣列
let arr = s.as_bytes();
for (i, &item) in arr.iter().enumerate() {
if item == b' ' {
return i;
}
}
s.len()
}
上面的例子可以實現獲取首個空格的索引,後續我們也可以通過這個索引來實現需求,但這種方式的問題是,我們獲取的索引和字串不是強關聯的,如果我們在使用索引之前,意外的對目標字串進行了修改,那麼這個索引也就失去它的意義了。
基於以上的問題,我們應該使用切片來建立與目標字串的強關聯,並且利用切片是不可變引用的特性,讓 Rust 編譯器來幫我們檢查 通過可變引用修改目標字串值 的不合理操作 (對於這裡有疑問的同學可以看我的上一篇分享 -《03-引用與借用》)
接下來我們使用切片來實現最初的需求
fn main() {
let str = String::from("hello world");
let first_word = slice_first_word(&str[..]);
println!("{}", first_word); // hello
}
fn slice_first_word(s: &str) -> &str {
// 將字串轉為字元陣列
let arr = s.as_bytes();
for (i, &item) in arr.iter().enumerate() {
// 判斷當前位是否是空格
if item == b' ' {
return &s[..i];
}
}
&s[..]
}
其他資料型別的切片
陣列
let arr = [1,2,3,4,5];
let slice = &arr[1..3];
println!("{:?}", slice); // [2,3]