use super::interval::merge_neighbours_with_same_class;
use crate::Interval;
use ord_subset::OrdSubset;
use ord_subset::OrdSubsetSliceExt;
use std::fmt::Debug;
use std::hash::Hash;
mod splits;
use splits::{intervals_from_splits, trim_splits};
pub fn find_intervals<A, C>(attribute: &[A], classes: &[C], small: usize) -> Vec<Interval<A, C>>
where
A: OrdSubset + Copy + Debug,
C: Eq + Hash + Copy + Debug,
{
let mut sorted: Vec<(&A, &C)> = Vec::new();
for (v, c) in attribute.iter().zip(classes.iter()) {
sorted.push((v, c));
}
sorted.ord_subset_sort_by_key(|pair| pair.0);
let mut split_index = Vec::new();
for (prev_index, ((cur_value, _cur_class), (prev_value, _prev_class))) in
sorted.iter().skip(1).zip(sorted.iter()).enumerate()
{
if cur_value > prev_value {
split_index.push(prev_index + 1);
}
}
let split_index_trimmed = trim_splits(split_index, small, &sorted);
let intervals: Vec<Interval<A, C>> = intervals_from_splits(split_index_trimmed, &sorted);
merge_neighbours_with_same_class(&intervals)
}
#[cfg(test)]
mod tests {
use super::find_intervals;
use super::Interval;
#[test]
fn test_golf_example() {
let attrbibute = vec![64, 65, 68, 69, 70, 71, 72, 72, 75, 75, 80, 81, 83, 85];
let classes = vec!["p", "d", "p", "p", "p", "d", "p", "d", "p", "p", "d", "p", "p", "d"];
let actual = find_intervals(&attrbibute, &classes, 3);
let expected = vec![Interval::lower(85, "p"), Interval::upper(85, "d")];
assert_eq!(expected, actual);
}
}
pub fn quantize<A, C>(intervals: &[Interval<A, C>], attribute_value: A) -> Option<&Interval<A, C>>
where
A: PartialOrd + Copy,
C: Copy,
{
intervals.iter().find(|interval| interval.matches(attribute_value))
}