前々回、前回に決定的な誤り発見。(1.10)をstd::iterのごとくに使用してますが、それはstd::ops::Range でした。共通するお名前で同様な機能のTraitsが実装されているのでイテレータとして練習してしまいました。今回「よく使いそうな奴ら」は気をつけたつもりなので大丈夫か?怪しいケド。
※「やっつけな日常」投稿順 Index はこちら
イテレータとレンジ
イテレータのドキュメントは以下です。
一方レンジのドキュメントは以下です。
内部に定義されたTraitを見ると、共通のお名前でほぼ似た機能多数が提供されています。それでついつい Rangeオブジェクトのメソッドを練習して、イテレータを練習した気になってました。すみません。ただ、前回、前々回と練習したのはどちらも同じような結果を得られる「簡単な奴ら」だったので、大勢に影響ないかと(いいわけ。)
今回練習してみる「奴ら」
今回練習してみるのは、
-
- filter
- map
- enumerate
- cmp
です。どれもよく使いそうな奴らでないかと。1のfilterは与えたクロージャを使い条件に一致するものだけをイテレータから取り出すもの。2のmapは、イテレータから取り出す要素にクロージャを作用させて変換した値を取り出すもの。3のenumerateは、要素だけでなく、取り出す順番のインデックス番号も同時にとりだすもの。最後のcmpは、イテレータ同士を比較するもの。
ソースが以下に。
fn main() { //filter let tgt = [1, 2, 3, 4, 5, 6, 7, 8, 9]; print!("filter:"); for item in tgt.iter().filter(|x| (*x % 3) == 0) { print!(" {}", item); } println!(); //map let tgt1 = [1, 2, 3, 4, 5, 6, 7, 8, 9]; print!("map:"); for item in tgt1.iter().map(|x| x * 2) { print!(" {}", item); } println!(); //enumerate let tgt2 = [1, 2, 3, 4, 5, 6, 7, 8, 9]; print!("enumerate:"); for (idx, item) in tgt2.iter().enumerate() { print!(" {}={}", idx, item); } println!(); //cmp let tgt3a = [1, 2, 3, 4, 5, 6, 7, 8, 9]; let tgt3b = [1, 2, 3, 4, 5, 6, 7, 8]; let tgt3c = [1, 2, 3, 4, 5, 6, 7, 8, 0]; let tgt3d = [1, 2, 3, 4, 5, 6, 7, 8, 9]; let tgt3e = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; println!("a:b {:?}", tgt3a.iter().cmp(tgt3b.iter())); println!("a:c {:?}", tgt3a.iter().cmp(tgt3c.iter())); println!("a:d {:?}", tgt3a.iter().cmp(tgt3d.iter())); println!("a:e {:?}", tgt3a.iter().cmp(tgt3e.iter())); }
実機上での実行結果
実機(WSL2 Ubuntu20.04LTS上の Rust)での実行結果が以下に。
filterで「3の倍数だけ取り出せ」と。できてますな。
mapで「倍の値にせよ」と。できてますな。
enumerateで「インデックス番号と要素を同時に取り出せ」と。これもOK。
コンペア結果も、長さが大きい方がGreater、長さが同じで要素も同じならEqual、でも要素が大なりならGreater、短かったら Less と。まあ、なっとくいく結果なんでないかい。