Rustでコレクション操作をしてみようとしたところ、基本的な部分ではありつつも、けっこう躓いたのでメモ。公式リファレンスが充実しているので、そちらを確認するのも良いですが、型引数が必要な箇所や、実際にそれをどう指定するのかまでは、例がまとまっていなかったので。

HTTPリクエストで与えられたクエリ文字列を、JSONに変換してレスポンスする、というケースを例にします。

今回のコードサンプルは以下。
https://github.com/yo1000/rust-hyper/tree/389b425ca8

要件

  • Rust 1.31.1
  • Cargo 1.31.0
$ rustc -V
rustc 1.31.1 (b6c32da9b 2018-12-18)

$ cargo -V
cargo 1.31.0 (339d9f9c8 2018-11-16)

コード例

今回はコード例から。コード内で使っている操作を個別に補足説明していくスタイル。

(&Method::GET, "/query_as_json") => {
    let query_as_map = match _req.uri().query() {
        Some(it) => {
            it.split('&')
                .map(|q| q.split('=')
                    .collect::<Vec<_>>())
                .filter(|q| q.len() >= 1)
                .map(|q| match q.len() {
                    1 => { (q[0], "") }
                    _ => { (q[0], q[1]) }
                })
                .collect::<HashMap<_, _>>()
        }
        None => { HashMap::new() }
    };

    Response::builder()
        .status(StatusCode::OK)
        .header("Content-Type", "application/json; charset=utf-8")
        .body(Body::from(json!(query_as_map).to_string()))
        .unwrap()
}

split

splitは他の言語同様、与えられたキーワードで文字列を分割するというものです。splitメソッドでは、Splitトレイトが返却されます。Splitトレイトには、Iteratorトレイトが実装されているため、これを基点に各種コレクション操作メソッドを呼び出せます。

collect

collectも他の言語同様、操作している反復子を目的のオブジェクトに集めることができます。集める先のオブジェクト型の指定には、::<_>でメソッドに型引数を与えたり、代入先の変数に型を明示することで推論させるような方法があります。

今回の例ではcollect::<Vec<_>>()と指定しているので、Iteratorの各オブジェクトが、Vecオブジェクトに集められます。

map

mapも他の言語同様、操作している反復子中の各オブジェクトを加工変換して、変換後のオブジェクトを割り当てることができます。mapメソッドでは、Mapトレイトが返却されます。Mapトレイトには、Iteratorトレイトが実装されているため、各種コレクション操作メソッドをチェーンできます。

先の例では、map(|q| q.split('=').collect::<Vec<_>>())のように指定しているので、反復子中の各文字列を=で分割して、これをVecに集めたものに変換、割り当てをしています。

filter

filterも他の言語同様、操作している反復子中の各オブジェクトを、条件によって絞り込むことができます。filterメソッドでは、Filterトレイトが返却されます。Filterトレイトには、Iteratorトレイトが実装されているため、各種コレクション操作メソッドをチェーンできます。

先の例では、filter(|q| q.len() >= 1)のように指定しているので、反復子中の各行列の長さが1以上のオブジェクトのみに絞り込みをしています。

参考

コレクション操作メソッドは他にもたくさんありますが、基本的に他の言語で提供されているものと機能は同じです。より詳しい内容については、公式ドキュメントのIteratorトレイトを確認してみてください。