2
0

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 1 year has passed since last update.

RustでGroupBy(ToDictionary)をしたい

Last updated at Posted at 2022-04-07

やりたいこと

Rustで配列内のデータをキー毎に集約する操作(group by)をしたい

#[derive(Clone, Debug)]
struct Hoge {
    a: String,
    b: i32,
}

let data = vec![
        Hoge {
            a: "a".to_string(),
            b: 1,
        },
        Hoge {
            a: "a".to_string(),
            b: 1,
        },
        Hoge {
            a: "b".to_string(),
            b: 0,
        },
        Hoge {
            a: "c".to_string(),
            b: 2,
        },
        Hoge {
            a: "a".to_string(),
            b: 2,
        },
    ];

といった時、dataをHoge.bで集約したいとする

最初に結論

foldでやるか、itertools.into_group_map_by がいいんじゃないかなと思う。

標準的アプロ―チ

foldを使う

// 型はBTreeMap<i32, Vec<Hoge>になる
let groups = data.iter().fold(
        BTreeMap::new(),
        |mut acc: BTreeMap<i32, Vec<Hoge>>, value| {
            acc.entry(value.b)
                .or_insert_with(Vec::new)
                .push(value.to_owned());
            acc
        },
    );

悪くはないのだが、個人的には直感的でないと感じてしまった。

grouping_by クレートを使う

こちらのクレート を使うと以下のように書ける

// 型はHashMap<i32, Vec<Hoge>になる
let groups = data.into_iter().grouping_by(|x| x.b.clone());

ただこのクレートはあまりメジャーでない

itertoolsを使う

itertools には、group_byというメソッドがある。こちらはC#やSQLのGroupByとはちょっと違う動きをする。

ただ、バージョン10.0.0から into_group_map_by というメソッドが追加されており、これだとC#やSQLのGroupByと同じ動きをするようだ。

// 型はHashMap<i32, Vec<Hoge>になる
let groups = data.into_iter().into_group_map_by(|x| x.b.clone());

このクレートなら他の便利なメソッドも使えるようになるし、これがよさそう。

まとめ

foldのやり方がピンとこなかったので、いろいろ調べました。itertoolsのgroup_byは罠ですね。

2
0
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
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?