Skip to content

Commit 7939ae9

Browse files
authored
Merge pull request #406 from cuviper/more-insert_sorted_by
Tweak and extend `insert sorted by`{,`_key`} methods
2 parents c0542d7 + 354345b commit 7939ae9

File tree

5 files changed

+97
-15
lines changed

5 files changed

+97
-15
lines changed

src/map.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -505,12 +505,12 @@ where
505505
/// pair is moved to or inserted at that position regardless.
506506
///
507507
/// Computes in **O(n)** time (average).
508-
pub fn insert_sorted_by<F>(&mut self, cmp: F, key: K, value: V) -> (usize, Option<V>)
508+
pub fn insert_sorted_by<F>(&mut self, key: K, value: V, mut cmp: F) -> (usize, Option<V>)
509509
where
510510
K: Ord,
511-
F: FnMut(&K, &V) -> Ordering,
511+
F: FnMut(&K, &V, &K, &V) -> Ordering,
512512
{
513-
let (Ok(i) | Err(i)) = self.binary_search_by(cmp);
513+
let (Ok(i) | Err(i)) = self.binary_search_by(|k, v| cmp(k, v, &key, &value));
514514
self.insert_before(i, key, value)
515515
}
516516

@@ -526,11 +526,11 @@ where
526526
/// pair is moved to or inserted at that position regardless.
527527
///
528528
/// Computes in **O(n)** time (average).
529-
pub fn insert_sorted_by_key<F, B>(
529+
pub fn insert_sorted_by_key<B, F>(
530530
&mut self,
531-
mut sort_key: F,
532531
key: K,
533532
value: V,
533+
mut sort_key: F,
534534
) -> (usize, Option<V>)
535535
where
536536
B: Ord,

src/map/core/entry.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use super::{equivalent, Entries, IndexMapCore, RefMut};
22
use crate::HashValue;
3+
use core::cmp::Ordering;
34
use core::{fmt, mem};
45
use hashbrown::hash_table;
56

@@ -402,6 +403,45 @@ impl<'a, K, V> VacantEntry<'a, K, V> {
402403
(i, self.shift_insert(i, value))
403404
}
404405

406+
/// Inserts the entry's key and the given value into the map at its ordered
407+
/// position among keys sorted by `cmp`, and returns the new index and a
408+
/// mutable reference to the value.
409+
///
410+
/// If the existing keys are **not** already sorted, then the insertion
411+
/// index is unspecified (like [`slice::binary_search`]), but the key-value
412+
/// pair is inserted at that position regardless.
413+
///
414+
/// Computes in **O(n)** time (average).
415+
pub fn insert_sorted_by<F>(self, value: V, mut cmp: F) -> (usize, &'a mut V)
416+
where
417+
K: Ord,
418+
F: FnMut(&K, &V, &K, &V) -> Ordering,
419+
{
420+
let slice = crate::map::Slice::from_slice(self.map.entries);
421+
let (Ok(i) | Err(i)) = slice.binary_search_by(|k, v| cmp(k, v, &self.key, &value));
422+
(i, self.shift_insert(i, value))
423+
}
424+
425+
/// Inserts the entry's key and the given value into the map at its ordered
426+
/// position using a sort-key extraction function, and returns the new index
427+
/// and a mutable reference to the value.
428+
///
429+
/// If the existing keys are **not** already sorted, then the insertion
430+
/// index is unspecified (like [`slice::binary_search`]), but the key-value
431+
/// pair is inserted at that position regardless.
432+
///
433+
/// Computes in **O(n)** time (average).
434+
pub fn insert_sorted_by_key<B, F>(self, value: V, mut sort_key: F) -> (usize, &'a mut V)
435+
where
436+
B: Ord,
437+
F: FnMut(&K, &V) -> B,
438+
{
439+
let search_key = sort_key(&self.key, &value);
440+
let slice = crate::map::Slice::from_slice(self.map.entries);
441+
let (Ok(i) | Err(i)) = slice.binary_search_by_key(&search_key, sort_key);
442+
(i, self.shift_insert(i, value))
443+
}
444+
405445
/// Inserts the entry's key and the given value into the map at the given index,
406446
/// shifting others to the right, and returns a mutable reference to the value.
407447
///

src/map/tests.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1232,14 +1232,14 @@ fn insert_sorted_by_key() {
12321232
let mut values = [(-1, 8), (3, 18), (-27, 2), (-2, 5)];
12331233
let mut map: IndexMap<i32, i32> = IndexMap::new();
12341234
for (key, value) in values {
1235-
let (_, old) = map.insert_sorted_by_key(|k, _| k.abs(), key, value);
1235+
let (_, old) = map.insert_sorted_by_key(key, value, |k, _| k.abs());
12361236
assert_eq!(old, None);
12371237
}
12381238
values.sort_by_key(|(key, _)| key.abs());
12391239
assert_eq!(values, *map.as_slice());
12401240

12411241
for (key, value) in &mut values {
1242-
let (_, old) = map.insert_sorted_by_key(|k, _| k.abs(), *key, -*value);
1242+
let (_, old) = map.insert_sorted_by_key(*key, -*value, |k, _| k.abs());
12431243
assert_eq!(old, Some(*value));
12441244
*value = -*value;
12451245
}
@@ -1251,14 +1251,14 @@ fn insert_sorted_by() {
12511251
let mut values = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5)];
12521252
let mut map: IndexMap<i32, i32> = IndexMap::new();
12531253
for (key, value) in values {
1254-
let (_, old) = map.insert_sorted_by(|probe, _| key.cmp(probe), key, value);
1254+
let (_, old) = map.insert_sorted_by(key, value, |key1, _, key2, _| key2.cmp(key1));
12551255
assert_eq!(old, None);
12561256
}
12571257
values.reverse();
12581258
assert_eq!(values, *map.as_slice());
12591259

12601260
for (key, value) in &mut values {
1261-
let (_, old) = map.insert_sorted_by(|probe, _| (*key).cmp(probe), *key, -*value);
1261+
let (_, old) = map.insert_sorted_by(*key, -*value, |key1, _, key2, _| key2.cmp(key1));
12621262
assert_eq!(old, Some(*value));
12631263
*value = -*value;
12641264
}

src/set.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -434,12 +434,14 @@ where
434434
/// is moved to or inserted at that position regardless.
435435
///
436436
/// Computes in **O(n)** time (average).
437-
pub fn insert_sorted_by<F>(&mut self, mut cmp: F, value: T) -> (usize, bool)
437+
pub fn insert_sorted_by<F>(&mut self, value: T, mut cmp: F) -> (usize, bool)
438438
where
439439
T: Ord,
440-
F: FnMut(&T) -> Ordering,
440+
F: FnMut(&T, &T) -> Ordering,
441441
{
442-
let (index, existing) = self.map.insert_sorted_by(|k, _| cmp(k), value, ());
442+
let (index, existing) = self
443+
.map
444+
.insert_sorted_by(value, (), |a, (), b, ()| cmp(a, b));
443445
(index, existing.is_none())
444446
}
445447

@@ -455,12 +457,12 @@ where
455457
/// is moved to or inserted at that position regardless.
456458
///
457459
/// Computes in **O(n)** time (average).
458-
pub fn insert_sorted_by_key<F, B>(&mut self, mut sort_key: F, value: T) -> (usize, bool)
460+
pub fn insert_sorted_by_key<B, F>(&mut self, value: T, mut sort_key: F) -> (usize, bool)
459461
where
460462
B: Ord,
461463
F: FnMut(&T) -> B,
462464
{
463-
let (index, existing) = self.map.insert_sorted_by_key(|k, _| sort_key(k), value, ());
465+
let (index, existing) = self.map.insert_sorted_by_key(value, (), |k, _| sort_key(k));
464466
(index, existing.is_none())
465467
}
466468

@@ -938,7 +940,7 @@ impl<T, S> IndexSet<T, S> {
938940
where
939941
F: FnMut(&T, &T) -> Ordering,
940942
{
941-
self.map.sort_by(move |a, _, b, _| cmp(a, b));
943+
self.map.sort_by(move |a, (), b, ()| cmp(a, b));
942944
}
943945

944946
/// Sort the values of the set and return a by-value iterator of

tests/quick.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,46 @@ quickcheck_limit! {
130130
true
131131
}
132132

133+
fn insert_sorted_by(insert: Vec<(u32, u32)>) -> bool {
134+
let mut hmap = HashMap::new();
135+
let mut map = IndexMap::new();
136+
let mut map2 = IndexMap::new();
137+
for &(key, value) in &insert {
138+
hmap.insert(key, value);
139+
map.insert_sorted_by(key, value, |key1, _, key2, _| key2.cmp(key1));
140+
match map2.entry(key) {
141+
Entry::Occupied(e) => *e.into_mut() = value,
142+
Entry::Vacant(e) => {
143+
e.insert_sorted_by(value, |key1, _, key2, _| key2.cmp(key1));
144+
}
145+
}
146+
}
147+
let hsorted = hmap.iter().sorted_by(|(key1, _), (key2, _)| key2.cmp(key1));
148+
itertools::assert_equal(hsorted, &map);
149+
itertools::assert_equal(&map, &map2);
150+
true
151+
}
152+
153+
fn insert_sorted_by_key(insert: Vec<(i32, u32)>) -> bool {
154+
let mut hmap = HashMap::new();
155+
let mut map = IndexMap::new();
156+
let mut map2 = IndexMap::new();
157+
for &(key, value) in &insert {
158+
hmap.insert(key, value);
159+
map.insert_sorted_by_key(key, value, |&k, _| (k.unsigned_abs(), k));
160+
match map2.entry(key) {
161+
Entry::Occupied(e) => *e.into_mut() = value,
162+
Entry::Vacant(e) => {
163+
e.insert_sorted_by_key(value, |&k, _| (k.unsigned_abs(), k));
164+
}
165+
}
166+
}
167+
let hsorted = hmap.iter().sorted_by_key(|(&k, _)| (k.unsigned_abs(), k));
168+
itertools::assert_equal(hsorted, &map);
169+
itertools::assert_equal(&map, &map2);
170+
true
171+
}
172+
133173
fn replace_index(insert: Vec<u8>, index: u8, new_key: u8) -> TestResult {
134174
if insert.is_empty() {
135175
return TestResult::discard();

0 commit comments

Comments
 (0)