43
24

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Rust windows (イテレーションの方)

Last updated at Posted at 2020-08-26

Rust の slice の windows (OS ではない)

使い方

「Rust windows」でググっても Windows(OS) で Rust をやってみる系の話しか出てこないので、書いておこうとなりました。

std::slice::windowsは、「前の値も含めて for ループを回したい」というユースケースで使うことができます。競技プログラミングなどでは頻出なのではないでしょうか。

let v = vec![1, 2, 3];
for w in v.windows(2) {
    let (prev, next) = (w[0], w[1]);
    println!("{} {}", prev, next)
}
// 1 2
// 2 3

windows メソッドを用いると、ミュータブルな変数を外側のスコープに用意するという手間を省くことができます。とてもきれいに書くことができるようになると思います。

また、引数に 2 を与えていることから察しがつくと思いますが、引数に与えたサイズのウィンドウでのイテレータを得ることができます。
引数に 3 などを与えると、3つずつのイテレータを得られます。

let v = vec![1, 2, 3, 4];
for w in v.windows(3) {
    let (prev, current, next) = (w[0], w[1], w[2]);
    println!("{} {} {}", prev, current, next)
}
// 1 2 3
// 2 3 4

注意

注意というほど注意でもないのですが、std::slice::Iterからは生えません。
iter()を挟むと、以下のようにコンパイルエラーとなります。

let v = vec![1, 2, 3];
for w in v.iter().windows(2) {
   let (prev, next) = (w[0], w[1]);
   println!("{} {}", prev, next)
}
// 1 2 
// 2 3 
   Compiling playground v0.0.1 (/playground)
error[E0599]: no method named `windows` found for struct `std::slice::Iter<'_, {integer}>` in the current scope
 --> src/main.rs:5:23
  |
5 |     for w in v.iter().windows(2) {
  |                       ^^^^^^^ method not found in `std::slice::Iter<'_, {integer}>`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0599`.
error: could not compile `playground`.

To learn more, run the command again with --verbose.

おそらく、サイズが決まっていて、s[lo..hi] のようにスライスでアクセスできるような並びに対してしか使えないことになっている(?)のだと思います。

itertools の windows

また、 itertools にはこれをタプルにした tuple_windowsがあります。
タプルにすると何がうれしいかというと、for文の1行目に書いているようなlet文の変数束縛フェーズがスキップできます。また、明示的に引数にサイズを与える必要もなくなり、for文の受け取り側のタプルの型から型推論してくれるようです。かしこい。

use itertools::Itertools;

fn main() {    
    let v = vec![1, 2, 3];
    for (prev, next) in v.iter().tuple_windows() {
        println!("{} {}", prev, next)
    }
    // 1 2 
    // 2 3 
}

こちらではiter()を挟まないと、「the method `tuple_windows` exists but the following trait bounds were not satisfied:」というエラーが出ます。 Rust 難しい…

43
24
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
43
24

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?