言語
日本語
English

Caution

お使いのブラウザはJavaScriptが無効になっております。
当サイトでは検索などの処理にJavaScriptを使用しています。
より快適にご利用頂くため、JavaScriptを有効にしたうえで当サイトを閲覧することをお勧めいたします。

Rust辞典

  1. トップページ
  2. Rust辞典
  3. スライス(&str / &[T])

スライス(&str / &[T])

スライスはコレクションの一部への参照で、所有権を持ちません。文字列スライス(&str)と配列スライス(&[T])の2種類があります。

構文

// 文字列スライス
let s: &str = "hello";           // 文字列リテラルは&strです。
let slice = &string[開始..終了]; // Stringから部分スライスを取得します。

// 配列スライス
let slice: &[i32] = &array[開始..終了];
let full: &[i32] = &array[..]; // 全体のスライスです。

スライス記法一覧

記法概要
&s[0..5]インデックス0から4まで(5は含まない)のスライスです。
&s[..5]先頭から4まで(開始省略)のスライスです。
&s[3..]インデックス3から末尾まで(終了省略)のスライスです。
&s[..]全体のスライスです。
&str文字列スライス型です。文字列リテラルの型でもあります。
&[T]型Tの配列スライス型です。

サンプルコード

sample_slice.rs
fn first_word(s: &str) -> &str {
    let bytes = s.as_bytes();
    for (i, &item) in bytes.iter().enumerate() {
        if item == b' ' {
            return &s[0..i]; // 最初の空白の前までを返します。
        }
    }
    &s[..] // 空白がなければ全体を返します。
}

fn sum_slice(nums: &[i32]) -> i32 {
    nums.iter().sum()
}

fn main() {
    // 文字列スライス
    let s = String::from("hello world");
    let hello = &s[0..5];
    let world = &s[6..11];
    println!("{} {}", hello, world); // 『hello world』と出力されます。

    let word = first_word(&s);
    println!("最初の単語: {}", word); // 『hello』と出力されます。

    // 配列スライス
    let a = [1, 2, 3, 4, 5];
    let slice = &a[1..4];
    println!("{:?}", slice); // 『[2, 3, 4]』と出力されます。

    println!("合計: {}", sum_slice(&a)); // 『15』と出力されます。
}
rustc slice.rs
./slice
hello world
最初の単語: hello
[2, 3, 4]
合計: 15
slice2.rs — スライスのメソッド操作
fn main() {
    let scores = [85, 92, 78, 96, 88, 71, 95];

    // 部分スライスを取得します。
    let top3 = &scores[..3];
    let last3 = &scores[scores.len() - 3..];
    println!("top3:  {:?}", top3);  // [85, 92, 78]
    println!("last3: {:?}", last3); // [71, 95] ← 実際は [88, 71, 95]

    // スライスのメソッドを使います。
    println!("len:  {}", scores.len());
    println!("contains 96: {}", scores.contains(&96));
    println!("iter sum: {}", scores.iter().sum::<i32>());

    // windows / chunks でまとめて処理します。
    println!("windows(3):");
    for w in scores.windows(3) {
        println!("  {:?}", w);
    }

    println!("chunks(3):");
    for chunk in scores.chunks(3) {
        println!("  {:?}", chunk);
    }
}
rustc slice2.rs
./slice2
top3:  [85, 92, 78]
last3: [88, 71, 95]
len:  7
contains 96: true
iter sum: 605
windows(3):
  [85, 92, 78]
  [92, 78, 96]
  [78, 96, 88]
  [96, 88, 71]
  [88, 71, 95]
chunks(3):
  [85, 92, 78]
  [96, 88, 71]
  [95]
slice3.rs — 可変スライスとsort/split
fn main() {
    let mut names = ["Vegeta", "Son Goku", "Piccolo", "Krillin", "Gohan"];

    // 可変スライスをソートします。
    names.sort();
    println!("sorted: {:?}", names);

    // splitで分割します(元の配列は変わりません)。
    let (first_half, second_half) = names.split_at(2);
    println!("first:  {:?}", first_half);
    println!("second: {:?}", second_half);

    // iterで変換します。
    let upper: Vec<String> = names.iter().map(|s| s.to_uppercase()).collect();
    println!("upper: {:?}", upper);
}
rustc slice3.rs
./slice3
sorted: ["Gohan", "Krillin", "Piccolo", "Son Goku", "Vegeta"]
first:  ["Gohan", "Krillin"]
second: ["Piccolo", "Son Goku", "Vegeta"]
upper: ["GOHAN", "KRILLIN", "PICCOLO", "SON GOKU", "VEGETA"]

概要

スライスは元のデータへの参照であるため、コピーは発生しません。関数引数に『String』の代わりに『&str』を使うと、文字列リテラルとStringの両方を受け取れるためより汎用的な設計になります。

マルチバイト文字(日本語など)を含む文字列をバイト境界ではないインデックスでスライスすると実行時パニックになります。文字単位で操作する場合は『chars()』メソッドを使用してください(String::chars())。

スライスのライフタイムは参照元のデータと結びついており、参照元が解放されるとスライスも無効になります。詳細はライフタイム('a)を参照してください。

記事の間違いや著作権の侵害等ございましたらお手数ですがまでご連絡頂ければ幸いです。