RustのVecの使い方【vec!, push, pop】

472, 2022-05-12

目次

RustのVecの使い方

Rustで可変長の配列を扱いたいとなったときに使用されるのがVecです。
RustではVecを使うことでヒープを利用した可変長配列を使うことができます。

この記事ではRustのVecについて使い方を解説します。
今回の記事のキーワードは「マクロ」です。

関連記事


Vecの初期化

Vecを作りたい場合は↓のフォーマットで定義します。

let 変数名: Vec<型> = Vec::new();

↑の場合は長さ0の空のベクタを定義する場合です。
コードでは↓になります。

    // 空のベクタ(整数)を作る場合
    let v0: Vec<i32> = Vec::new();

    println!("{}", v0.len());  // 0

ベクタのlen()を使うと現在のベクタの長さを取得できます。
↑のようにベクタを初期化した場合は長さが0になっているのがわかります。

マクロを使った初期化

Vec::new()とか書くのがめんどくさいので、Rustではベクタ初期化用のマクロを用意してくれています。
その名もvec![]です。

たとえば整数の型を持つ空のベクタを定義したい場合は↓のようにします。

    // マクロを使って空のベクタ(整数)を作る場合
    let v1 = vec![0; 0];

    println!("{}", v1.len());  // 0

あるいは特定の数列などでベクタを初期化したい場合、整数のときは↓のように書けます。

    // マクロを使ってベクタを特定の値で初期化する場合
    let v2 = vec![1, 2, 3];

    println!("len is {}", v2.len());  // 3
    println!("{}", v2[0]);  // 1
    println!("{}", v2[1]);  // 2
    println!("{}", v2[2]);  // 3

マクロが型について自動で判断してくれているので、型名を書かなくて済みます。
あるいは整数のベクタの場合は↓のようにすると特定の要素数を0クリアして作成できます。

    // マクロを使って3要素のベクタを0クリアする場合
    let v3 = vec![0; 3];

    println!("len is {}", v3.len());  // 3
    println!("{}", v3[0]);  // 0
    println!("{}", v3[1]);  // 0
    println!("{}", v3[2]);  // 0

ベクタの末尾に値をpushする

ベクタを使っていてベクタの末尾、おしりに値を追加したいケースがあります。
そういう時はベクタのpush()を使います。

    // pushでベクタの末尾に値を追加する
    let mut v4 = vec![1, 2];

    println!("len is {}", v4.len());  // 2

    v4.push(3);

    println!("len is {}", v4.len());  // 3
    println!("{}", v4[0]);  // 1
    println!("{}", v4[1]);  // 2
    println!("{}", v4[2]);  // 3

長さが2だったベクタv4push(3)で3の値を追加しています。
そうするとベクタの長さは3になり、ベクタの末尾の要素に3が追加されます。

pushは「押し込む」とか「入れ込む」とかそういう意味です。

ベクタの末尾から値をpopする

ベクタの末尾から値をポップする場合はベクタのpop()を使います。

    // popでベクタの末尾から値をポップする
    let mut v5 = vec![1, 2, 3];
    let popped = v5.pop();

    println!("len is {}", v5.len());  // 2
    println!("popped {}", popped.unwrap());  // 3

↑の例ではベクタv5はマクロvec![1, 2, 3]で初期化されています。
この場合、pop()を使うとベクタの末尾の3の要素が取り除かれてポップされます。

ポップ後のベクタの長さは1減っていて、poppedにはポップされた要素のOptionが格納されます。
poppedの値を取り出したい場合はunwrap()を使います。

空のベクタでpop()を使った場合はNoneが返ってきます。

    // 空のベクタでpopを使うとNoneが返ってくる
    let mut v5_2 = vec![0; 0];
    let popped = v5_2.pop();
    if popped == None {
        println!("vector is empty!");
    }

ベクタから値をポップする場合は、ポップした要素がNoneかどうか確認するようにしておきましょう。
Noneをunwrap()してprintln!()などで参照しようとするとパニックになることがあります。

ベクタをfor文で回す

ベクタはfor文で回すことができます。
↓のようにベクタをfor文に渡すと回せます。

    // ベクタをfor文で回す
    let v6 = vec![1, 2, 3];

    for el in v6 {
        println!("{}", el);
        // 1
        // 2
        // 3
    }

iter()を使っても同様です。

    // ベクタをiter()とfor文で回す
    let v7 = vec![1, 2, 3];

    for el in v7.iter() {
        println!("{}", el);
        // 1
        // 2
        // 3
    }

for文の中で添え字と要素を同時に扱いたい場合はiter()enumerate()を組み合わせて使います。

    // ベクタをiter()とenumerate()とfor文で回す
    let v8 = vec![1, 2, 3];

    for (i, el) in v8.iter().enumerate() {
        println!("{} {}", i, el);
        // 0 1
        // 1 2
        // 2 3
    }

あるいは愚直に回して添え字を使って要素を参照する方法もあります。
この方法は一番柔軟なので覚えておいて損はないでしょう。

    // 愚直に添え字で回す方法
    let v9 = vec![1, 2, 3];

    for i in 0..v9.len() {
        println!("{} {}", i, v9[i]);
    }

おわりに

今回はRustのVecについて解説しました。
Vecはよく使うデータ型と言えます。

(^ _ ^)

ベクターでデータを管理しよう

(・ v ・)

プッシュ、ポップ



この記事のアンケートを送信する