Rust入門系列之切片

木木劍光發表於2022-02-11

切片

切片是 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]

相關文章