Skip to content

Commit 12c4c89

Browse files
committed
FEAT: Implement in-place sorting with .sort_by()
1 parent ff0757e commit 12c4c89

File tree

2 files changed

+80
-0
lines changed

2 files changed

+80
-0
lines changed

src/lib.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1110,6 +1110,53 @@ impl<K, V, S> OrderMap<K, V, S>
11101110
});
11111111
}
11121112

1113+
pub fn sort_by<F>(&mut self, mut compare: F)
1114+
where F: FnMut(&K, &V, &K, &V) -> Ordering,
1115+
{
1116+
// new_index will form a lookup map from current index -> new index.
1117+
let mut new_index = Vec::from_iter(0..self.len());
1118+
new_index.sort_by(|&i, &j| {
1119+
let ei = &self.entries[i];
1120+
let ej = &self.entries[j];
1121+
compare(&ei.key, &ei.value, &ej.key, &ej.value)
1122+
});
1123+
1124+
// Apply new index to self.indices
1125+
dispatch_32_vs_64!(self.apply_new_index(&new_index));
1126+
1127+
// Apply new index to entries
1128+
apply_permutation(&mut new_index, &mut self.entries);
1129+
1130+
/// Apply a permutation
1131+
///
1132+
/// perm: Each index 0..v.len() appear exactly once.
1133+
fn apply_permutation<T>(perm: &mut [usize], v: &mut [T]) {
1134+
debug_assert_eq!(perm.len(), v.len());
1135+
1136+
for i in 0..perm.len() {
1137+
let mut current = i;
1138+
while i != perm[current] {
1139+
let next = perm[current];
1140+
// move element from next to current
1141+
v.swap(next, current);
1142+
perm[current] = current;
1143+
current = next;
1144+
}
1145+
perm[current] = current;
1146+
}
1147+
}
1148+
}
1149+
1150+
fn apply_new_index<Sz>(&mut self, new_index: &[usize])
1151+
where Sz: Size
1152+
{
1153+
for pos in self.indices.iter_mut() {
1154+
if let Some((i, _)) = pos.resolve::<Sz>() {
1155+
pos.set_pos::<Sz>(new_index[i]);
1156+
}
1157+
}
1158+
}
1159+
11131160
/// Sort the key-value pairs of the map and return a by value iterator of
11141161
/// the key-value pairs with the result.
11151162
///

tests/quick.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,39 @@ quickcheck! {
302302
}
303303
}
304304

305+
fn sort_1(keyvals: Large<Vec<(i8, i8)>>) -> () {
306+
let mut map: OrderMap<_, _> = OrderMap::from_iter(keyvals.to_vec().into_iter());
307+
let mut answer = keyvals.0;
308+
answer.sort_by_key(|t| t.0);
309+
310+
// reverse dedup: Because OrderMap::from_iter keeps the last value for
311+
// identical keys
312+
answer.reverse();
313+
answer.dedup_by_key(|t| t.0);
314+
answer.reverse();
315+
316+
map.sort_by(|k1, _, k2, _| Ord::cmp(k1, k2));
317+
let mapv = Vec::from_iter(map);
318+
assert_eq!(answer, mapv);
319+
}
320+
321+
fn sort_2(keyvals: Large<Vec<(i8, i8)>>) -> () {
322+
let mut map: OrderMap<_, _> = OrderMap::from_iter(keyvals.to_vec().into_iter());
323+
map.sort_by(|_, v1, _, v2| Ord::cmp(v1, v2));
324+
assert_sorted_by_key(map, |t| t.1);
325+
}
326+
}
327+
328+
fn assert_sorted_by_key<I, Key, X>(iterable: I, key: Key)
329+
where I: IntoIterator,
330+
I::Item: Ord + Clone + Debug,
331+
Key: Fn(&I::Item) -> X,
332+
X: Ord,
333+
{
334+
let input = Vec::from_iter(iterable);
335+
let mut sorted = input.clone();
336+
sorted.sort_by_key(key);
337+
assert_eq!(input, sorted);
305338
}
306339

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

0 commit comments

Comments
 (0)