2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

配列

同じ型の固定長の要素数を持つ型です。一度宣言するとサイズは変えられません。そのため、宣言時にサイズがわかっているケースで利用します。型定義は[型; サイズ]で行います。

宣言

let arr: [i32; 3] = [1, 2, 3];

参照

println!("{}", arr[0]); // 1

他の言語と同様、サイズを超えたインデックスを与えるとプログラムは異常終了(パニック)します。

配列は宣言時に要素の型とサイズがわかっているので、トータルで必要なメモリサイズが計算できます。そのためデータはスタックに格納され、アクセスが高速になります。

 

タプル

固定長で複数の値をまとめあげる点では配列と似ていますが、各要素の型は必ずしも一致している必要はありません。

宣言

let tup: (i32, f64, &str) = (42, 3.14, "hello");

参照

println!("{}", tup.0); // 42
println!("{}", tup.1); // 3.14
println!("{}", tup.2); // hello

ベクタ

同じ型の可変長の要素を持ちます。配列と違い、宣言後に要素を追加したり削除したりできます。配列よりは低速度ですが、コレクションのサイズを柔軟に変えたい場合はベクタを使用します。

宣言

Vec::newを使う方法とvec!を使う方法があります。どちらも結果は同じです。

let mut vec1: Vec<i32> = Vec::new();
vec1.push(1);
vec1.push(2);

let vec2 = vec![3, 4, 5];

参照

[]の中にインデックスを指定する方法とgetメソッドを使う方法があります。前者は配列同様パニックを起こす可能性がありますが、後者はOptionを返すのでその恐れはありません。

println!("{}", vec2[0]); // 3
if let Some(value) = vec2.get(1) {
    println!("{}", value); // 4
}

更新

pushpopなど、用途に応じたメソッドが利用できます。

vec1.push(6);
vec1.pop();

スライス

スライスはコレクションそのものではなく、あるコレクションの一部への参照を持つ変数です。すでに何かしらのコレクション(例えば配列)があったとして、そのコレクションの一部(全部も可能)を参照する形で宣言されます。
宣言時は&コレクション名[範囲]の形で指定します。

let arr: [i32; 3] = [1, 2, 3];

let slice = &arr[0..2]; // [1, 2]
println!("{:?}", slice);

文字列スライス

スライスは様々なコレクションに対して作成でき、文字列もその対象です。文字列は&str型として扱えるため、文字列の一部分を参照する場合は&strに対するスライスを利用できます。

let s = "hello world";
let hello = &s[0..5];
let world = &s[6..];
println!("{}, {}", hello, world); // hello, world

ただし、このスライスの1要素はバイト単位であるため、マルチバイト文字を含む場合は「1要素=1文字」とは限りません。そのようなケースを想定するのであれば、for文などを使って処理しましょう。

コレクションのまとめ

今回取り上げたコレクションの違いをまとめてみます。

種類 要素の型 サイズ
配列 すべて同じ 固定
タプル バラバラでもOK 固定
ベクタ すべて同じ 可変

固定長と可変長で明確に分けているのでその点に注意しましょう。基本的にはベクタのほうが出番が多そうなイメージです。
TypeScriptのオブジェクトのように違う意味を持つ値をまとめて扱いたいが、それぞれに名前をつけるほどではない、みたいなケースでタプルが活用できそうです(TypeScriptにもタプルがありますが、そうやって使うイメージ)。

for文で使うには

配列

そのままでは使えないので、参照を渡すかiterメソッドを利用しましょう。

for val in &arr {
    println!("{}", val);
}

タプル

iterメソッドを利用します。

let tuples = [(1, "one"), (2, "two")];
for (num, word) in tuples.iter() {
    println!("{}: {}", num, word);
}

ベクタ

そのままfor文で使えますが、所有権が移動してしまうので、参照を渡しましょう。

for val in &vec2 {
    println!("{}", val);
}

様々なメソッド

コレクション(正確に言えばIteratorトレイトを実装している型)にはいくつかのメソッドが用意されています。
そのうちの主なものを紹介します。

map

let vec2 = vec![3, 4, 5];

let doubled: Vec<i32> = vec2.iter().map(|x| x * 2).collect();
println!("{:?}", doubled); // [6, 8, 10]

filter

let vec2 = vec![3, 4, 5];

let evens: Vec<i32> = vec2.iter().filter(|&&x| x % 2 == 0).cloned().collect();
println!("{:?}", evens); // [4]

fold

let vec2 = vec![3, 4, 5];

let sum: i32 = vec2.iter().fold(0, |acc, &x| acc + x);
println!("{}", sum); // 12

このあたりはTypeScriptと似ていますね(reduceがRustではfoldになる?)。やはりコレクションから使えるメソッドは慣れると直感的に書けて筆者は好きです。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?