1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
//! イテレータのグルーピング。

use std::collections::BTreeMap;

/// イテレータのグルーピング。
///
/// # Suggestions
/// `BTreeMap` と `HashMap` 用で分けるべき? メソッド名を冗長にしたくない。
///
/// # See also
/// [`UsizeGroupBy`]
///
/// [`UsizeGroupBy`]: trait.UsizeGroupBy.html
pub trait GroupBy<V> {
    /// # Examples
    /// ```
    /// use nekolib::traits::GroupBy;
    ///
    /// let a = vec![1, 4, 3, -5, -6, 0, 2, -2, 3];
    /// let g1 = a.iter().copied().group_by(|&ai: &i32| ai.rem_euclid(3));
    /// let g2 = a.iter().copied().group_by(|&ai: &i32| ai % 3);
    ///
    /// assert_eq!(g1.len(), 3);
    /// assert_eq!(g1[&0], [3, -6, 0, 3]);
    /// assert_eq!(g1[&1], [1, 4, -5, -2]);
    /// assert_eq!(g1[&2], [2]);
    ///
    /// assert_eq!(g2.len(), 4);
    /// assert_eq!(g2[&-2], [-5, -2]);
    /// assert_eq!(g2[&0], [3, -6, 0, 3]);
    /// assert_eq!(g2[&1], [1, 4]);
    /// assert_eq!(g2[&2], [2]);
    /// ```
    fn group_by<K: Ord>(self, key: impl FnMut(&V) -> K) -> BTreeMap<K, Vec<V>>;
}

impl<V, I: Iterator<Item = V>> GroupBy<V> for I {
    fn group_by<K: Ord>(
        self,
        mut key: impl FnMut(&V) -> K,
    ) -> BTreeMap<K, Vec<V>> {
        let mut res = BTreeMap::new();
        for v in self {
            let k = key(&v);
            res.entry(k).or_insert(vec![]).push(v);
        }
        res
    }
}