map、filter、collect
シーケンスを変換します
「map、filter、collect」はCoddyKit上の無料Learn Rust Codingレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはLearn Rust Coding学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Learn Rust Codingコースには全4レッスンが含まれています。
シーケンスの変換
イテレータパイプラインで主に使うメソッドは3つあります。mapは各要素を変換し、filterは一部の要素を残し、collectは結果をコレクションにまとめます。
これらを組み合わせると、多くの手動ループを短く読みやすいチェーンに置き換えられます。
map: 1つ入力して1つ出力
mapはすべての要素にクロージャを適用し、変換後の値を生成します。要素数は変わらず、値だけが変わります。
遅延評価されるため、クロージャはイテレータが消費されるときにだけ実行されます。
fn main() {
let nums = vec![1, 2, 3];
let doubled: Vec<i32> = nums.iter().map(|x| x * 2).collect();
println!("{:?}", doubled);
}mapは型を変更できる
mapの出力型は入力型と同じである必要はありません。ここでは数値を文字列に変換します。
そのためmapは、データをある形から別の形へ変換するのに最適です。
fn main() {
let nums = vec![1, 2, 3];
let labels: Vec<String> = nums.iter().map(|x| format!("n{}", x)).collect();
println!("{:?}", labels);
}filter: 必要なものだけ残す
filterはboolを返すクロージャを受け取ります。その結果がtrueになる要素は残り、それ以外は破棄されます。
クロージャは参照を受け取るため、*でデリファレンスするか、パターンマッチングを使うことがよくあります。
fn main() {
let nums = vec![1, 2, 3, 4, 5, 6];
let evens: Vec<i32> = nums.into_iter().filter(|x| x % 2 == 0).collect();
println!("{:?}", evens);
}mapとfilterのチェーン
アダプターは自由につなげられます。順序が重要で、各要素はチェーンを上から下へ順に通過します。
ここでは偶数を残してから、残った値を二乗します。
fn main() {
let result: Vec<i32> = (1..=6)
.filter(|x| x % 2 == 0)
.map(|x| x * x)
.collect();
println!("{:?}", result);
}Vecにcollectする
collectはイテレータを消費し、コレクションを構築します。使用できるコレクション型が多いため、通常は対象の型を注釈します。
ターボフィッシュ構文collect::<Vec<_>>()を使えば、変数に型を注釈する代わりにできます。
fn main() {
let squares = (1..=4).map(|x| x * x).collect::<Vec<i32>>();
println!("{:?}", squares);
}Stringにcollectする
collectはベクタに限られません。charのイテレータはStringにcollectできます。
Rustは対象の型を使って、要素をどのように組み立てるかを決定します。
fn main() {
let shouted: String = "hello".chars().map(|c| c.to_ascii_uppercase()).collect();
println!("{}", shouted);
}HashMapにcollectする
キーと値のタプルのイテレータは、HashMapにcollectできます。zipで要素を組み合わせるか、mapでタプルを作成します。
2つの並行するシーケンスからルックアップテーブルを構築する、すっきりした方法です。
use std::collections::HashMap;
fn main() {
let map: HashMap<i32, i32> = (1..=3).map(|x| (x, x * x)).collect();
println!("{:?}", map.get(&2));
}3つすべてを組み合わせる
典型的なパイプラインは文章のように読めます。要素を取り出し、絞り込み、変換し、まとめます。
ここでは3文字より長い単語を残し、大文字に変換します。
fn main() {
let words = vec!["hi", "rust", "go", "code"];
let kept: Vec<String> = words
.into_iter()
.filter(|w| w.len() > 3)
.map(|w| w.to_uppercase())
.collect();
println!("{:?}", kept);
}filter_map: 絞り込みと変換を同時に行う
filter_mapはOptionを返すクロージャを適用します。Some(v)は残されてアンラップされ、Noneは破棄されます。
一部の入力が無効になる可能性があるパース処理で特に役立ちます。
fn main() {
let inputs = vec!["1", "two", "3"];
let nums: Vec<i32> = inputs
.into_iter()
.filter_map(|s| s.parse::<i32>().ok())
.collect();
println!("{:?}", nums);
}このパターンが優れている理由
map/filter/collectパイプラインは宣言的です。ループをどのように行うかではなく、求める結果を記述します。これにより、オフバイワンエラーや途中の可変状態を避けられます。
さらに遅延評価のおかげで、ステップの間に一時的なベクタが作られることもありません。
クイックチェック
シーケンスの変換について、どれだけ理解できているか確認しましょう。
まとめ
実用的なイテレータパイプラインを構築できるようになりました。
mapは各要素を変換し、型を変更することもできますfilterは述語がtrueになる要素を残しますcollectは結果をVec、String、HashMapなどにまとめますfilter_mapはOptionを使って、1つのステップで絞り込みと変換を行います
よくある質問
「map、filter、collect」レッスンは無料ですか?
はい。「map、filter、collect」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Learn Rust Codingコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Learn Rust Codingコースには全4レッスンが含まれています。
「map、filter、collect」で何を学びますか?
シーケンスを変換します ブラウザで直接実行するハンズオンコードでLearn Rust Codingを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Learn Rust Codingを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのLearn Rust Codingは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。
「map、filter、collect」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このLearn Rust Codingレッスンでコードを書いて実行できますか?
はい。すべてのLearn Rust Codingレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- Iteratorトレイト
- map、filter、collect
- アダプターとコンシューマー
- カスタムイテレーター