standing_relations/convenience/
reduce.rs

1use std::{
2    collections::{BTreeMap, HashMap},
3    hash::Hash,
4};
5
6use crate::{core::Reduce, CountMap, IsReduce, Observable, Op, Relation};
7
8impl<C: Op> Relation<C>
9where
10    C::D: Clone + Eq + Hash,
11{
12    pub fn counts(
13        self,
14    ) -> Relation<impl IsReduce<T = ((C::D, isize), isize), OM = HashMap<C::D, isize>>> {
15        self.map_h(|x| (x, ()))
16            .reduce_(|_, &n| n)
17            .type_named("counts")
18    }
19    pub fn distinct(self) -> Relation<impl Op<D = C::D>> {
20        self.map_h(|x| (x, ()))
21            .reduce_(|_, _: &isize| ())
22            .map_h(|(x, ())| x)
23            .type_named("distinct")
24    }
25}
26
27impl<C: Op<D = (K, V)>, K: Clone + Eq + Hash, V> Relation<C> {
28    #[allow(clippy::type_complexity)]
29    pub fn reduce_<M: CountMap<V> + Observable, Y: Clone + Eq, F: Fn(&K, &M) -> Y>(
30        self,
31        f: F,
32    ) -> Relation<Reduce<K, V, C, M, Y, HashMap<K, Y>, F>> {
33        self.reduce_with_output_(f)
34    }
35    pub fn reduce<Y: Clone + Eq>(
36        self,
37        f: impl Fn(&K, &HashMap<V, isize>) -> Y,
38    ) -> Relation<impl IsReduce<T = ((K, Y), isize), OM = HashMap<K, Y>>>
39    where
40        V: Eq + Hash,
41    {
42        self.reduce_::<HashMap<V, isize>, _, _>(f)
43    }
44    pub fn group_min(self) -> Relation<impl IsReduce<T = ((K, V), isize), OM = HashMap<K, V>>>
45    where
46        V: Clone + Ord,
47    {
48        self.reduce_(|_, m: &BTreeMap<V, isize>| m.keys().next().unwrap().clone())
49            .type_named("group_min")
50    }
51    pub fn group_max(self) -> Relation<impl IsReduce<T = ((K, V), isize), OM = HashMap<K, V>>>
52    where
53        V: Clone + Ord,
54    {
55        self.reduce_(|_, m: &BTreeMap<V, isize>| m.keys().next_back().unwrap().clone())
56            .type_named("group_max")
57    }
58}