Skip to content

Commit d856ee7

Browse files
committed
Add sorted_by_cached_key to Itertools trait
Fixes #424. This function is a wrapper around `slice::sort_by_cached_key`.
1 parent b6c99ba commit d856ee7

File tree

2 files changed

+62
-0
lines changed

2 files changed

+62
-0
lines changed

src/lib.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2667,6 +2667,43 @@ pub trait Itertools : Iterator {
26672667
v.into_iter()
26682668
}
26692669

2670+
/// Sort all iterator elements into a new iterator in ascending order. The key function is
2671+
/// called exactly once per key.
2672+
///
2673+
/// **Note:** This consumes the entire iterator, uses the
2674+
/// [`slice::sort_by_cached_key`] method and returns the result as a new
2675+
/// iterator that owns its elements.
2676+
///
2677+
/// The sorted iterator, if directly collected to a `Vec`, is converted
2678+
/// without any extra copying or allocation cost.
2679+
///
2680+
/// ```
2681+
/// use itertools::Itertools;
2682+
///
2683+
/// // sort people in descending order by age
2684+
/// let people = vec![("Jane", 20), ("John", 18), ("Jill", 30), ("Jack", 27)];
2685+
///
2686+
/// let oldest_people_first = people
2687+
/// .into_iter()
2688+
/// .sorted_by_cached_key(|x| -x.1)
2689+
/// .map(|(person, _age)| person);
2690+
///
2691+
/// itertools::assert_equal(oldest_people_first,
2692+
/// vec!["Jill", "Jack", "Jane", "John"]);
2693+
/// ```
2694+
/// ```
2695+
#[cfg(feature = "use_alloc")]
2696+
fn sorted_by_cached_key<K, F>(self, f: F) -> VecIntoIter<Self::Item>
2697+
where
2698+
Self: Sized,
2699+
K: Ord,
2700+
F: FnMut(&Self::Item) -> K,
2701+
{
2702+
let mut v = Vec::from_iter(self);
2703+
v.sort_by_cached_key(f);
2704+
v.into_iter()
2705+
}
2706+
26702707
/// Sort the k smallest elements into a new iterator, in ascending order.
26712708
///
26722709
/// **Note:** This consumes the entire iterator, and returns the result

tests/test_std.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,31 @@ fn sorted_by_key() {
510510
it::assert_equal(v, vec![4, 3, 2, 1, 0]);
511511
}
512512

513+
#[test]
514+
fn sorted_by_cached_key() {
515+
// Track calls to key function
516+
let mut ncalls = 0;
517+
518+
let sorted = [3, 4, 1, 2].iter().cloned().sorted_by_cached_key(|&x| {
519+
ncalls += 1;
520+
x.to_string()
521+
});
522+
it::assert_equal(sorted, vec![1, 2, 3, 4]);
523+
// Check key function called once per element
524+
assert_eq!(ncalls, 4);
525+
526+
let mut ncalls = 0;
527+
528+
let sorted = (0..5).sorted_by_cached_key(|&x| {
529+
ncalls += 1;
530+
-x
531+
});
532+
it::assert_equal(sorted, vec![4, 3, 2, 1, 0]);
533+
// Check key function called once per element
534+
assert_eq!(ncalls, 5);
535+
}
536+
537+
513538
#[test]
514539
fn test_multipeek() {
515540
let nums = vec![1u8,2,3,4,5];

0 commit comments

Comments
 (0)