From d856ee74b1b6e8427f9ee09f581850cc0bcfd4a2 Mon Sep 17 00:00:00 2001 From: Justin Prieto Date: Mon, 6 Sep 2021 17:49:37 -0400 Subject: [PATCH 1/2] Add `sorted_by_cached_key` to `Itertools` trait Fixes #424. This function is a wrapper around `slice::sort_by_cached_key`. --- src/lib.rs | 37 +++++++++++++++++++++++++++++++++++++ tests/test_std.rs | 25 +++++++++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 55c895844..37d2d52ff 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2667,6 +2667,43 @@ pub trait Itertools : Iterator { v.into_iter() } + /// Sort all iterator elements into a new iterator in ascending order. The key function is + /// called exactly once per key. + /// + /// **Note:** This consumes the entire iterator, uses the + /// [`slice::sort_by_cached_key`] method and returns the result as a new + /// iterator that owns its elements. + /// + /// The sorted iterator, if directly collected to a `Vec`, is converted + /// without any extra copying or allocation cost. + /// + /// ``` + /// use itertools::Itertools; + /// + /// // sort people in descending order by age + /// let people = vec![("Jane", 20), ("John", 18), ("Jill", 30), ("Jack", 27)]; + /// + /// let oldest_people_first = people + /// .into_iter() + /// .sorted_by_cached_key(|x| -x.1) + /// .map(|(person, _age)| person); + /// + /// itertools::assert_equal(oldest_people_first, + /// vec!["Jill", "Jack", "Jane", "John"]); + /// ``` + /// ``` + #[cfg(feature = "use_alloc")] + fn sorted_by_cached_key(self, f: F) -> VecIntoIter + where + Self: Sized, + K: Ord, + F: FnMut(&Self::Item) -> K, + { + let mut v = Vec::from_iter(self); + v.sort_by_cached_key(f); + v.into_iter() + } + /// Sort the k smallest elements into a new iterator, in ascending order. /// /// **Note:** This consumes the entire iterator, and returns the result diff --git a/tests/test_std.rs b/tests/test_std.rs index 819995861..0dc772a29 100644 --- a/tests/test_std.rs +++ b/tests/test_std.rs @@ -510,6 +510,31 @@ fn sorted_by_key() { it::assert_equal(v, vec![4, 3, 2, 1, 0]); } +#[test] +fn sorted_by_cached_key() { + // Track calls to key function + let mut ncalls = 0; + + let sorted = [3, 4, 1, 2].iter().cloned().sorted_by_cached_key(|&x| { + ncalls += 1; + x.to_string() + }); + it::assert_equal(sorted, vec![1, 2, 3, 4]); + // Check key function called once per element + assert_eq!(ncalls, 4); + + let mut ncalls = 0; + + let sorted = (0..5).sorted_by_cached_key(|&x| { + ncalls += 1; + -x + }); + it::assert_equal(sorted, vec![4, 3, 2, 1, 0]); + // Check key function called once per element + assert_eq!(ncalls, 5); +} + + #[test] fn test_multipeek() { let nums = vec![1u8,2,3,4,5]; From a1510e74053b36a44d1e9179e067d614987c91b1 Mon Sep 17 00:00:00 2001 From: Justin Prieto Date: Mon, 6 Sep 2021 19:47:15 -0400 Subject: [PATCH 2/2] remove extra space --- tests/test_std.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/test_std.rs b/tests/test_std.rs index 0dc772a29..2049d1597 100644 --- a/tests/test_std.rs +++ b/tests/test_std.rs @@ -534,7 +534,6 @@ fn sorted_by_cached_key() { assert_eq!(ncalls, 5); } - #[test] fn test_multipeek() { let nums = vec![1u8,2,3,4,5];