質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.46%
Rust

Rustは、MoFoが支援するプログラミング言語。高速性を維持しつつも、メモリ管理を安全に行うことが可能な言語です。同じコンパイル言語であるC言語やC++では困難だったマルチスレッドを実装しやすく、並行性という点においても優れています。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

Q&A

解決済

3回答

6026閲覧

[Rust] ベクタの一部分を切り抜きたい

rtgsdfsdg

総合スコア174

Rust

Rustは、MoFoが支援するプログラミング言語。高速性を維持しつつも、メモリ管理を安全に行うことが可能な言語です。同じコンパイル言語であるC言語やC++では困難だったマルチスレッドを実装しやすく、並行性という点においても優れています。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

0グッド

1クリップ

投稿2021/07/04 02:48

RustでPythonでいうスライス機能に該当する機能はありますか?数十分調べましたがそれは時間をただ消費したので知識人の力を借りたいです。

python

1# Pythonで言うところのこの機能 2a = [0, 1, 2] 3a[1:] # [1, 2] 4a[0:1] # [0, 1]

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答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
qryxip

総合スコア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

qnighy

総合スコア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

TaniguchiTakaki

総合スコア171

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.46%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問