use std::{cmp::Ord, collections::HashSet, hash::Hash, iter::Peekable};
pub trait UniqueElements<T> {
fn unique(&mut self)
where
T: Eq + Hash + Clone;
fn unique_ordered(&mut self)
where
T: Eq + Ord;
}
impl<T> UniqueElements<T> for Vec<T> {
fn unique(&mut self)
where
T: Eq + Hash + Clone,
{
let mut seen = HashSet::new();
self.retain(|x| {
seen.insert(x.clone()) });
}
fn unique_ordered(&mut self)
where
T: Eq + Ord,
{
self.sort_unstable();
self.dedup();
}
}
pub trait IteratorExt: Iterator + Sized {
fn get_unique(self) -> UniqueIterator<Self> {
UniqueIterator::new(self)
}
fn skip_last(self) -> SkipLastIterator<Self> {
SkipLastIterator::new(self)
}
}
impl<I: Iterator> IteratorExt for I {}
pub struct UniqueIterator<I: Iterator> {
iter: I,
seen: HashSet<I::Item>,
}
impl<I: Iterator> UniqueIterator<I> {
fn new(iter: I) -> UniqueIterator<I> {
UniqueIterator {
iter,
seen: HashSet::new(),
}
}
}
impl<I> Iterator for UniqueIterator<I>
where
I: Iterator,
I::Item: Eq + Hash + Clone,
{
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
self.iter.find(|item| self.seen.insert(item.clone()))
}
}
pub struct SkipLastIterator<I: Iterator> {
iter: Peekable<I>,
}
impl<I: Iterator> SkipLastIterator<I> {
fn new(iter: I) -> SkipLastIterator<I> {
SkipLastIterator {
iter: iter.peekable(),
}
}
}
impl<I: Iterator> Iterator for SkipLastIterator<I> {
type Item = I::Item;
fn next(&mut self) -> Option<I::Item> {
let next_item = self.iter.next();
match self.iter.peek() {
Some(_) => {
next_item
}
None => {
None
}
}
}
}
#[cfg(test)]
mod tests_iterator_ext {
use super::*;
#[test]
fn test_get_unique() {
let numbers = vec![1, 3, 2, 2, 5, 2, 3, 4];
let unique_numbers: Vec<_> = numbers.into_iter().get_unique().collect();
assert_eq!(unique_numbers, &[1, 3, 2, 5, 4]);
}
#[test]
fn test_get_unique_empty() {
let numbers: Vec<i32> = vec![];
let unique_numbers: Vec<_> = numbers.into_iter().get_unique().collect();
assert_eq!(unique_numbers, &[]);
}
#[test]
fn test_get_unique_all_same() {
let numbers = vec![1, 1, 1, 1, 1];
let unique_numbers: Vec<_> = numbers.into_iter().get_unique().collect();
assert_eq!(unique_numbers, &[1]);
}
#[test]
fn test_get_unique_strings() {
let strings = vec!["a", "b", "b", "c", "a", "d", "c", "b", "e"];
let unique_strings: Vec<_> = strings.into_iter().get_unique().collect();
assert_eq!(unique_strings, &["a", "b", "c", "d", "e"]);
}
#[test]
fn test_skip_last() {
let iter = 1..=5;
let data1: Vec<_> = iter.skip_last().collect();
assert_eq!(data1, [1, 2, 3, 4]);
}
#[test]
fn test_skip_last_empty() {
let iter: Vec<i32> = vec![];
let data1: Vec<_> = iter.into_iter().skip_last().collect();
assert_eq!(data1, []);
}
#[test]
fn test_skip_last_one_element() {
let iter = vec![1];
let data1: Vec<_> = iter.into_iter().skip_last().collect();
assert_eq!(data1, []);
}
#[test]
fn test_skip_last_multiple_skips() {
let data2: Vec<_> = [1, 2, 3, 4, 5]
.into_iter()
.skip(1)
.skip_last()
.skip(1)
.collect();
assert_eq!(data2, [3, 4]);
}
#[test]
fn test_skip_last_chained_skips() {
let data3: Vec<_> = [1, 2, 3]
.into_iter()
.skip_last()
.skip_last()
.skip_last()
.collect();
assert!(data3.is_empty());
}
#[test]
fn test_skip_last_strings() {
let strings = vec!["a", "b", "c", "d", "e"];
let skipped_strings: Vec<_> = strings.into_iter().skip_last().collect();
assert_eq!(skipped_strings, &["a", "b", "c", "d"]);
}
}
#[cfg(test)]
mod tests_unique_elements {
use super::*;
#[test]
fn test_unique() {
let mut vec = vec![1, 2, 2, 3, 1, 4, 3, 2, 5];
vec.unique();
assert_eq!(vec, vec![1, 2, 3, 4, 5]);
}
#[test]
fn test_unique_empty() {
let mut vec: Vec<i32> = vec![];
vec.unique();
assert_eq!(vec, Vec::<i32>::new());
assert_eq!(vec, vec![] as Vec<i32>); }
#[test]
fn test_unique_all_same() {
let mut vec = vec![1, 1, 1, 1, 1];
vec.unique();
assert_eq!(vec, vec![1]);
}
#[test]
fn test_unique_strings() {
let mut vec = vec!["a", "b", "b", "c", "a", "d", "c", "b", "e"];
vec.unique();
assert_eq!(vec, vec!["a", "b", "c", "d", "e"]);
}
#[test]
fn test_unique_ordered() {
let mut vec = vec![1, 2, 2, 3, 1, 4, 3, 2, 5];
vec.unique_ordered();
assert_eq!(vec, vec![1, 2, 3, 4, 5]);
}
#[test]
fn test_unique_ordered_empty() {
let mut vec: Vec<i32> = vec![];
vec.unique_ordered();
assert_eq!(vec, Vec::<i32>::new());
}
#[test]
fn test_unique_ordered_all_same() {
let mut vec = vec![1, 1, 1, 1, 1];
vec.unique_ordered();
assert_eq!(vec, vec![1]);
}
#[test]
fn test_unique_ordered_strings() {
let mut vec = vec!["a", "b", "b", "c", "a", "d", "c", "b", "e"];
vec.unique_ordered();
assert_eq!(vec, vec!["a", "b", "c", "d", "e"]);
}
#[test]
fn test_unique_mixed_types() {
let mut vec: Vec<String> = vec![
"a".to_string(),
"b".to_string(),
"b".to_string(),
"c".to_string(),
"a".to_string(),
];
vec.unique();
assert_eq!(vec, vec!["a".to_string(), "b".to_string(), "c".to_string()]);
}
#[test]
fn test_unique_ordered_mixed_types() {
let mut vec: Vec<String> = vec![
"a".to_string(),
"b".to_string(),
"b".to_string(),
"c".to_string(),
"a".to_string(),
];
vec.unique_ordered();
assert_eq!(vec, vec!["a".to_string(), "b".to_string(), "c".to_string()]);
}
#[test]
fn test_unique_numbers() {
let mut vec = vec![5, 4, 3, 2, 1, 1, 2, 3, 4, 5];
vec.unique();
assert_eq!(vec, vec![5, 4, 3, 2, 1]);
}
#[test]
fn test_unique_ordered_numbers() {
let mut vec = vec![5, 4, 3, 2, 1, 1, 2, 3, 4, 5];
vec.unique_ordered();
assert_eq!(vec, vec![1, 2, 3, 4, 5]);
}
#[test]
fn test_unique_already_unique() {
let mut vec = vec![1, 2, 3, 4, 5];
vec.unique();
assert_eq!(vec, vec![1, 2, 3, 4, 5]);
}
#[test]
fn test_unique_ordered_already_unique() {
let mut vec = vec![1, 2, 3, 4, 5];
vec.unique_ordered();
assert_eq!(vec, vec![1, 2, 3, 4, 5]);
}
#[test]
fn test_unique_negative_numbers() {
let mut vec = vec![-1, -2, -2, -3, -1, -4, -3, -2, -5];
vec.unique();
assert_eq!(vec, vec![-1, -2, -3, -4, -5]);
}
#[test]
fn test_unique_ordered_negative_numbers() {
let mut vec = vec![-1, -2, -2, -3, -1, -4, -3, -2, -5];
vec.unique_ordered();
assert_eq!(vec, vec![-5, -4, -3, -2, -1]);
}
#[test]
fn test_unique_mixed_positive_negative() {
let mut vec = vec![-1, 2, -2, 3, -1, 4, -3, 2, -5];
vec.unique();
assert_eq!(vec, vec![-1, 2, -2, 3, 4, -3, -5]);
}
#[test]
fn test_unique_ordered_mixed_positive_negative() {
let mut vec = vec![-1, 2, -2, 3, -1, 4, -3, 2, -5];
vec.unique_ordered();
assert_eq!(vec, vec![-5, -3, -2, -1, 2, 3, 4]);
}
#[derive(Debug, Hash, PartialEq, Eq, Clone)]
struct MyStruct {
value: i32,
}
impl Ord for MyStruct {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.value.cmp(&other.value)
}
}
impl PartialOrd for MyStruct {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
#[test]
fn test_unique_structs() {
let mut vec = vec![
MyStruct { value: 1 },
MyStruct { value: 2 },
MyStruct { value: 2 },
MyStruct { value: 3 },
MyStruct { value: 1 },
];
vec.unique();
assert_eq!(
vec,
vec![
MyStruct { value: 1 },
MyStruct { value: 2 },
MyStruct { value: 3 },
]
);
}
#[test]
fn test_unique_ordered_structs() {
let mut vec = vec![
MyStruct { value: 3 },
MyStruct { value: 1 },
MyStruct { value: 2 },
MyStruct { value: 2 },
MyStruct { value: 1 },
];
vec.unique_ordered();
assert_eq!(
vec,
vec![
MyStruct { value: 1 },
MyStruct { value: 2 },
MyStruct { value: 3 },
]
);
}
}