From cc88a2d26c4e5ba60728d5d43743279f5c135a5e Mon Sep 17 00:00:00 2001 From: JarredAllen Date: Tue, 11 Aug 2020 22:33:08 -0700 Subject: [PATCH 1/2] Create counts method and tests for it --- src/lib.rs | 24 ++++++++++++++++++++++++ tests/test_std.rs | 13 +++++++++++++ 2 files changed, 37 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index eeecb1bb0..1412930b1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2807,6 +2807,30 @@ pub trait Itertools : Iterator { { multipeek_impl::multipeek(self) } + + /// Collect the items in this iterator and return a `HashMap` which + /// contains each item that appears in the iterator and the number + /// of times it appears. + /// + /// # Examples + /// ``` + /// # use itertools::Itertools; + /// let counts = [1, 1, 1, 3, 3, 5].into_iter().counts(); + /// assert_eq!(counts[&1], 3); + /// assert_eq!(counts[&3], 2); + /// assert_eq!(counts[&5], 1); + /// assert_eq!(counts.get(&0), None); + /// ``` + #[cfg(feature = "use_std")] + fn counts(self) -> HashMap + where + Self: Sized, + Self::Item: Eq + Hash, + { + let mut counts = HashMap::new(); + self.for_each(|item| *counts.entry(item).or_default() += 1); + counts + } } impl Itertools for T where T: Iterator { } diff --git a/tests/test_std.rs b/tests/test_std.rs index 9918592cb..0b28541f3 100644 --- a/tests/test_std.rs +++ b/tests/test_std.rs @@ -913,3 +913,16 @@ fn tree_fold1() { assert_eq!(actual, expected); } } + +#[test] +fn counts() { + let a: [usize; 0] = []; + assert_eq!(0, a.iter().counts().len()); + let b = [1, 1, 1, 2, 2, 3]; + let b_counts = b.iter().counts(); + assert_eq!(3, b_counts.len()); + assert_eq!(Some(&3), b_counts.get(&1)); + assert_eq!(Some(&2), b_counts.get(&2)); + assert_eq!(Some(&1), b_counts.get(&3)); + assert_eq!(None, b_counts.get(&4)); +} From 1d05c2bb00d2bd118850baa227022ccb95d26f1b Mon Sep 17 00:00:00 2001 From: JarredAllen Date: Tue, 18 Aug 2020 09:01:51 -0700 Subject: [PATCH 2/2] Change test to quickcheck --- tests/quick.rs | 21 +++++++++++++++++++++ tests/test_std.rs | 13 ------------- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/tests/quick.rs b/tests/quick.rs index d509c7929..8208a887c 100644 --- a/tests/quick.rs +++ b/tests/quick.rs @@ -1188,3 +1188,24 @@ quickcheck! { } } } + +quickcheck! { + #[test] + fn counts(nums: Vec) -> TestResult { + let counts = nums.iter().counts(); + for (&item, &count) in counts.iter() { + if count <= 0 { + return TestResult::failed(); + } + if count != nums.iter().filter(|&x| x == item).count() { + return TestResult::failed(); + } + } + for item in nums.iter() { + if !counts.contains_key(item) { + return TestResult::failed(); + } + } + TestResult::passed() + } +} diff --git a/tests/test_std.rs b/tests/test_std.rs index 0b28541f3..9918592cb 100644 --- a/tests/test_std.rs +++ b/tests/test_std.rs @@ -913,16 +913,3 @@ fn tree_fold1() { assert_eq!(actual, expected); } } - -#[test] -fn counts() { - let a: [usize; 0] = []; - assert_eq!(0, a.iter().counts().len()); - let b = [1, 1, 1, 2, 2, 3]; - let b_counts = b.iter().counts(); - assert_eq!(3, b_counts.len()); - assert_eq!(Some(&3), b_counts.get(&1)); - assert_eq!(Some(&2), b_counts.get(&2)); - assert_eq!(Some(&1), b_counts.get(&3)); - assert_eq!(None, b_counts.get(&4)); -}