Skip to content

Commit 3307e4d

Browse files
bors[bot]density
andauthored
Merge #575
575: Add `sorted_by_cached_key` to `Itertools` trait r=jswrenn a=density Fixes #424. This function is a wrapper around `slice::sort_by_cached_key`. Added tests similar to those for `sorted_by_key`. New code is formatted using `rustfmt`. Co-authored-by: Justin Prieto <justin@prieto.nyc>
2 parents ed55a5f + a1510e7 commit 3307e4d

File tree

2 files changed

+61
-0
lines changed

2 files changed

+61
-0
lines changed

src/lib.rs

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

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

tests/test_std.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,30 @@ 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+
513537
#[test]
514538
fn test_multipeek() {
515539
let nums = vec![1u8,2,3,4,5];

0 commit comments

Comments
 (0)