Skip to content

Commit 2251730

Browse files
authored
Merge pull request #244 from cuviper/sort_by_cached_key
Add `sort_by_cached_key` and `par_sort_by_cached_key`
2 parents 8e4cc9a + 8b7f398 commit 2251730

File tree

7 files changed

+70
-1
lines changed

7 files changed

+70
-1
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ bench = false
1818
arbitrary = { version = "1.0", optional = true, default-features = false }
1919
quickcheck = { version = "1.0", optional = true, default-features = false }
2020
serde = { version = "1.0", optional = true, default-features = false }
21-
rayon = { version = "1.4.1", optional = true }
21+
rayon = { version = "1.5.3", optional = true }
2222

2323
# Internal feature, only used when building as part of rustc,
2424
# not part of the stable interface of this crate.

RELEASES.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@
2020
- `IndexMap` and `IndexSet` both implement `arbitrary::Arbitrary<'_>` and
2121
`quickcheck::Arbitrary` if those optional dependency features are enabled.
2222

23+
- `IndexMap` and `IndexSet` now have `sort_by_cached_key` and
24+
`par_sort_by_cached_key` methods which perform stable sorts in place
25+
using a key extraction function.
26+
2327
- The `hashbrown` dependency has been updated to version 0.13.
2428

2529
- 1.9.1

src/map.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -736,6 +736,24 @@ where
736736
IntoIter::new(entries)
737737
}
738738

739+
/// Sort the map’s key-value pairs in place using a sort-key extraction function.
740+
///
741+
/// During sorting, the function is called at most once per entry, by using temporary storage
742+
/// to remember the results of its evaluation. The order of calls to the function is
743+
/// unspecified and may change between versions of `indexmap` or the standard library.
744+
///
745+
/// Computes in **O(m n + n log n + c)** time () and **O(n)** space, where the function is
746+
/// **O(m)**, *n* is the length of the map, and *c* the capacity. The sort is stable.
747+
pub fn sort_by_cached_key<T, F>(&mut self, mut sort_key: F)
748+
where
749+
T: Ord,
750+
F: FnMut(&K, &V) -> T,
751+
{
752+
self.with_entries(move |entries| {
753+
entries.sort_by_cached_key(move |a| sort_key(&a.key, &a.value));
754+
});
755+
}
756+
739757
/// Reverses the order of the map’s key-value pairs in place.
740758
///
741759
/// Computes in **O(n)** time and **O(1)** space.

src/rayon/map.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,18 @@ where
504504
entries.par_sort_unstable_by(move |a, b| cmp(&a.key, &a.value, &b.key, &b.value));
505505
IntoParIter { entries }
506506
}
507+
508+
/// Sort the map’s key-value pairs in place and in parallel, using a sort-key extraction
509+
/// function.
510+
pub fn par_sort_by_cached_key<T, F>(&mut self, sort_key: F)
511+
where
512+
T: Ord + Send,
513+
F: Fn(&K, &V) -> T + Sync,
514+
{
515+
self.with_entries(move |entries| {
516+
entries.par_sort_by_cached_key(move |a| sort_key(&a.key, &a.value));
517+
});
518+
}
507519
}
508520

509521
/// A parallel mutable iterator over the values of a `IndexMap`.

src/rayon/set.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,17 @@ where
572572
entries.par_sort_unstable_by(move |a, b| cmp(&a.key, &b.key));
573573
IntoParIter { entries }
574574
}
575+
576+
/// Sort the set’s values in place and in parallel, using a key extraction function.
577+
pub fn par_sort_by_cached_key<K, F>(&mut self, sort_key: F)
578+
where
579+
K: Ord + Send,
580+
F: Fn(&T) -> K + Sync,
581+
{
582+
self.with_entries(move |entries| {
583+
entries.par_sort_by_cached_key(move |a| sort_key(&a.key));
584+
});
585+
}
575586
}
576587

577588
/// Requires crate feature `"rayon"`.

src/set.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -633,6 +633,24 @@ where
633633
IntoIter::new(entries)
634634
}
635635

636+
/// Sort the set’s values in place using a key extraction function.
637+
///
638+
/// During sorting, the function is called at most once per entry, by using temporary storage
639+
/// to remember the results of its evaluation. The order of calls to the function is
640+
/// unspecified and may change between versions of `indexmap` or the standard library.
641+
///
642+
/// Computes in **O(m n + n log n + c)** time () and **O(n)** space, where the function is
643+
/// **O(m)**, *n* is the length of the map, and *c* the capacity. The sort is stable.
644+
pub fn sort_by_cached_key<K, F>(&mut self, mut sort_key: F)
645+
where
646+
K: Ord,
647+
F: FnMut(&T) -> K,
648+
{
649+
self.with_entries(move |entries| {
650+
entries.sort_by_cached_key(move |a| sort_key(&a.key));
651+
});
652+
}
653+
636654
/// Reverses the order of the set’s values in place.
637655
///
638656
/// Computes in **O(n)** time and **O(1)** space.

tests/quick.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,12 @@ quickcheck_limit! {
452452
assert_sorted_by_key(map, |t| t.1);
453453
}
454454

455+
fn sort_3(keyvals: Large<Vec<(i8, i8)>>) -> () {
456+
let mut map: IndexMap<_, _> = IndexMap::from_iter(keyvals.to_vec());
457+
map.sort_by_cached_key(|&k, _| std::cmp::Reverse(k));
458+
assert_sorted_by_key(map, |t| std::cmp::Reverse(t.0));
459+
}
460+
455461
fn reverse(keyvals: Large<Vec<(i8, i8)>>) -> () {
456462
let mut map: IndexMap<_, _> = IndexMap::from_iter(keyvals.to_vec());
457463

0 commit comments

Comments
 (0)