RustでPythonでいうスライス機能に該当する機能はありますか?数十分調べましたがそれは時間をただ消費したので知識人の力を借りたいです。
python
1# Pythonで言うところのこの機能 2a = [0, 1, 2] 3a[1:] # [1, 2] 4a[0:1] # [0, 1]
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

回答3件
0
ベストアンサー
ご提示のPythonコードであれば、このように記述することもできます。ただしPythonとは違い、Rustの[T]
, [T; N]
, Vec<T>
に対する添字は範囲外だとパニックが発生することに注意してください。
rust
1let a/*: [i32; 3]*/ = [0, 1, 2]; 2 3// これでも同様 4//let a = vec![0, 1, 2]; 5 6let _ = &a[1..]; 7let _ = &a[0..1];
TaniguchiTakakiさんが提示した<[T]>::getの場合、返り値はOption<T>となり、「範囲内ならこう、範囲外ならこう」という分岐が可能になります。
rust
1let array = [1, 2, 3]; 2 3if let Some(part) = array.get(1..) { 4 println!("{:?}", part); 5} else { 6 // この分岐では`part`は使用できない 7 println!("out of bound"); 8}
Pythonのsliceとは違い、[]
の中に直接入れるときとそうでないときで記法は変わりません。
rust
1let range = 1..; 2let _ = a[range];
もう一つ大きな違いとしては、[]の中に入れられる範囲はstep
のような情報を持ちません。stepしたい場合はイテレータで解決する必要があります。
rust
1let a = [1, 2, 3, 4, 5]; 2let part = a.iter().copied().step_by(2).collect::<Vec<_>>(); 3assert_eq!([1, 3, 5], *part);
ちなみに「スライス」という語はRustにおいても存在しますが、違うものを指します。スライス、[T]は長さがコンパイル時に定まらない列のことです。[T; N] (配列)やVec<T> (「ベクタ」と発音)の中身をスライスと取ることもできます。スライスの参照ではないスライスの実体そのものは、そのまま変数を束縛することができません。
rust
1let slice_ref = &[1, 2, 3][..]; // 配列[i32; 3]の全範囲をスライスと取り、その参照を取る 2let _ = *slice_ref; // これはOK。実体そのもので変数を束縛する訳ではないので。 3let slice = *slice_ref; 4// error[E0277]: the size for values of type `[{integer}]` cannot be known at compilation time 5// --> src/main.rs:4:9 6// | 7// 4 | let slice = *slice_ref; 8// | ^^^^^ doesn't have a size known at compile-time 9// | 10// = help: the trait `Sized` is not implemented for `[{integer}]` 11// = note: all local variables must have a statically known size 12// = help: unsized locals are gated as an unstable feature
投稿2021/07/04 08:28
編集2021/07/04 08:31総合スコア86
0
&a[1..]
, &a[0..=1]
のように書けます。
rust
1fn main() { 2 let a = vec![0, 1, 2]; 3 // a[1:] 相当: &a[1..] 4 assert_eq!(&a[1..], &[1, 2]); 5 // a[0:1] 相当: &a[0..=1] 6 assert_eq!(&a[0..=1], &[0, 1]); 7}
範囲記法は6種類あり、std::ops::Range のドキュメントに書いてあります。
rust
1a[..] // 全て 2a[1..] // 1以上 3a[..2] // 2未満 4a[1..2] // 1以上2未満 5a[..=2] // 2以下 6a[1..=2] // 1以上2以下
a[1..2]
などの式で得られるのは [T]
型の左辺値です。これをそのまま使うとコンパイルが通らないことが多く、 &a[..]
の形で出てくることが多いです。
rust
1fn main() { 2 let a = [1,2,3][..]; 3 //~^ERROR the size for values of type `[{integer}]` cannot be known at compilation time 4}
借用 (&[T]
) ではなく所有権のある値 (Vec<T>
) が欲しければ、 to_owned()
などで取り出すことができます (要素のコピーが発生します)
rust
1let b = a[1..2].to_owned();
投稿2021/07/04 08:07
総合スコア210
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
rust
1fn main() { 2 let v = vec![0, 1, 2]; 3 let x = v.as_slice().get(1..).unwrap(); 4 println!("{:?}", x); // [1, 2] 5 let x = v.as_slice().get(0..=1).unwrap(); 6 println!("{:?}", x); // [0, 1] 7 8}
こんな感じでどうでしょうか
投稿2021/07/04 07:11
総合スコア171
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。