Skip to content

Commit 3df49ba

Browse files
committed
FEAT: Implement in-place sorting with .sort_by()
1 parent 891161c commit 3df49ba

File tree

2 files changed

+80
-0
lines changed

2 files changed

+80
-0
lines changed

src/lib.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1044,6 +1044,52 @@ impl<K, V, S> OrderMap<K, V, S>
10441044
}
10451045
}
10461046

1047+
pub fn sort_by<F>(&mut self, mut compare: F)
1048+
where F: FnMut(&K, &V, &K, &V) -> Ordering,
1049+
{
1050+
// new_index will form a lookup map from current index -> new index.
1051+
let mut new_index = Vec::from_iter(0..self.len());
1052+
new_index.sort_by(|&i, &j| {
1053+
let ei = &self.entries[i];
1054+
let ej = &self.entries[j];
1055+
compare(&ei.key, &ei.value, &ej.key, &ej.value)
1056+
});
1057+
1058+
// Apply new index to self.indices
1059+
dispatch_32_vs_64!(self.apply_new_index(&new_index));
1060+
1061+
// Apply new index to entries
1062+
apply_permutation(&mut new_index, &mut self.entries);
1063+
1064+
/// Apply a permutation
1065+
///
1066+
/// perm: Each index 0..v.len() appear exactly once.
1067+
fn apply_permutation<T>(perm: &mut [usize], v: &mut [T]) {
1068+
debug_assert_eq!(perm.len(), v.len());
1069+
1070+
for i in 0..perm.len() {
1071+
let mut current = i;
1072+
while i != perm[current] {
1073+
let next = replace(&mut perm[current], current);
1074+
// move element from next to current
1075+
v.swap(next, current);
1076+
current = next;
1077+
}
1078+
perm[current] = current;
1079+
}
1080+
}
1081+
}
1082+
1083+
fn apply_new_index<Sz>(&mut self, new_index: &[usize])
1084+
where Sz: Size
1085+
{
1086+
for pos in self.indices.iter_mut() {
1087+
if let Some((i, _)) = pos.resolve::<Sz>() {
1088+
pos.set_pos::<Sz>(new_index[i]);
1089+
}
1090+
}
1091+
}
1092+
10471093
/// Sort the key-value pairs of the map and return a by value iterator of
10481094
/// the key-value pairs with the result.
10491095
///

tests/quick.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,40 @@ quickcheck! {
273273
// check the order
274274
itertools::assert_equal(map.keys(), initial_map.keys().filter(|&k| !remove_map.contains_key(k)));
275275
}
276+
277+
fn sort_1(keyvals: Large<Vec<(i8, i8)>>) -> () {
278+
let mut map: OrderMap<_, _> = OrderMap::from_iter(keyvals.to_vec());
279+
let mut answer = keyvals.0;
280+
answer.sort_by_key(|t| t.0);
281+
282+
// reverse dedup: Because OrderMap::from_iter keeps the last value for
283+
// identical keys
284+
answer.reverse();
285+
answer.dedup_by_key(|t| t.0);
286+
answer.reverse();
287+
288+
map.sort_by(|k1, _, k2, _| Ord::cmp(k1, k2));
289+
let mapv = Vec::from_iter(map);
290+
assert_eq!(answer, mapv);
291+
}
292+
293+
fn sort_2(keyvals: Large<Vec<(i8, i8)>>) -> () {
294+
let mut map: OrderMap<_, _> = OrderMap::from_iter(keyvals.to_vec());
295+
map.sort_by(|_, v1, _, v2| Ord::cmp(v1, v2));
296+
assert_sorted_by_key(map, |t| t.1);
297+
}
298+
}
299+
300+
fn assert_sorted_by_key<I, Key, X>(iterable: I, key: Key)
301+
where I: IntoIterator,
302+
I::Item: Ord + Clone + Debug,
303+
Key: Fn(&I::Item) -> X,
304+
X: Ord,
305+
{
306+
let input = Vec::from_iter(iterable);
307+
let mut sorted = input.clone();
308+
sorted.sort_by_key(key);
309+
assert_eq!(input, sorted);
276310
}
277311

278312
#[derive(Clone, Debug, Hash, PartialEq, Eq)]

0 commit comments

Comments
 (0)