diff --git a/src/lib.rs b/src/lib.rs index 7cd451d1f..6c60213ea 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -66,6 +66,8 @@ use std::iter::{IntoIterator, once}; use std::cmp::Ordering; use std::fmt; #[cfg(feature = "use_std")] +use std::collections::HashSet; +#[cfg(feature = "use_std")] use std::hash::Hash; #[cfg(feature = "use_alloc")] use std::fmt::Write; @@ -1671,6 +1673,30 @@ pub trait Itertools : Iterator { } } + /// Check whether all elements are unique (non equal). + /// + /// Empty iterators are considered to have unique elements: + /// + /// ``` + /// use itertools::Itertools; + /// + /// let data = vec![1, 2, 3, 4, 1, 5]; + /// assert!(!data.iter().all_unique()); + /// assert!(data[0..4].iter().all_unique()); + /// assert!(data[1..6].iter().all_unique()); + /// + /// let data : Option = None; + /// assert!(data.into_iter().all_unique()); + /// ``` + #[cfg(feature = "use_std")] + fn all_unique(&mut self) -> bool + where Self: Sized, + Self::Item: Eq + Hash + { + let mut used = HashSet::new(); + self.all(move |elt| used.insert(elt)) + } + /// Consume the first `n` elements from the iterator eagerly, /// and return the same iterator again. /// diff --git a/tests/test_std.rs b/tests/test_std.rs index d1ff815da..4f99b8258 100644 --- a/tests/test_std.rs +++ b/tests/test_std.rs @@ -189,6 +189,13 @@ fn all_equal() { } } +#[test] +fn all_unique() { + assert!("ABCDEFGH".chars().all_unique()); + assert!(!"ABCDEFGA".chars().all_unique()); + assert!(::std::iter::empty::().all_unique()); +} + #[test] fn test_put_back_n() { let xs = [0, 1, 1, 1, 2, 1, 3, 3];