standing_relations/convenience/
reduce.rs1use 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}