Skip to content

Commit 8c9df6b

Browse files
authored
Merge pull request rust-lang#128 from linclelinkpart5/master
Adding `reverse()` to `IndexMap` & `IndexSet`
2 parents da18351 + a442475 commit 8c9df6b

File tree

3 files changed

+86
-0
lines changed

3 files changed

+86
-0
lines changed

src/map.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1253,6 +1253,13 @@ where
12531253
self.into_iter()
12541254
}
12551255

1256+
/// Reverses the order of the map’s key-value pairs in place.
1257+
///
1258+
/// Computes in **O(n)** time and **O(1)** space.
1259+
pub fn reverse(&mut self) {
1260+
self.core.reverse()
1261+
}
1262+
12561263
/// Clears the `IndexMap`, returning all key-value pairs as a drain iterator.
12571264
/// Keeps the allocated memory for reuse.
12581265
pub fn drain(&mut self, range: RangeFull) -> Drain<K, V> {
@@ -1752,6 +1759,25 @@ impl<K, V> OrderMapCore<K, V> {
17521759
self.restore_hash_index(side_index);
17531760
}
17541761

1762+
fn reverse(&mut self) {
1763+
self.entries.reverse();
1764+
1765+
// No need to save hash indices, can easily calculate what they should
1766+
// be, given that this is an in-place reversal.
1767+
dispatch_32_vs_64!(self => apply_new_index(&mut self.indices, self.entries.len()));
1768+
1769+
fn apply_new_index<Sz>(indices: &mut [Pos], len: usize)
1770+
where
1771+
Sz: Size,
1772+
{
1773+
for pos in indices {
1774+
if let Some((i, _)) = pos.resolve::<Sz>() {
1775+
pos.set_pos::<Sz>(len - i - 1);
1776+
}
1777+
}
1778+
}
1779+
}
1780+
17551781
fn save_hash_index(&mut self) -> Vec<usize> {
17561782
// Temporarily use the hash field in a bucket to store the old index.
17571783
// Save the old hash values in `side_index`. Then we can sort

src/set.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,13 @@ where
527527
}
528528
}
529529

530+
/// Reverses the order of the set’s values in place.
531+
///
532+
/// Computes in **O(n)** time and **O(1)** space.
533+
pub fn reverse(&mut self) {
534+
self.map.reverse()
535+
}
536+
530537
/// Clears the `IndexSet`, returning all values as a drain iterator.
531538
/// Keeps the allocated memory for reuse.
532539
pub fn drain(&mut self, range: RangeFull) -> Drain<T> {

tests/quick.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,59 @@ quickcheck! {
330330
map.sort_by(|_, v1, _, v2| Ord::cmp(v1, v2));
331331
assert_sorted_by_key(map, |t| t.1);
332332
}
333+
334+
fn reverse(keyvals: Large<Vec<(i8, i8)>>) -> () {
335+
let mut map: IndexMap<_, _> = IndexMap::from_iter(keyvals.to_vec());
336+
337+
fn generate_answer(input: &Vec<(i8, i8)>) -> Vec<(i8, i8)> {
338+
// to mimic what `IndexMap::from_iter` does:
339+
// need to get (A) the unique keys in forward order, and (B) the
340+
// last value of each of those keys.
341+
342+
// create (A): an iterable that yields the unique keys in ltr order
343+
let mut seen_keys = HashSet::new();
344+
let unique_keys_forward = input.iter().filter_map(move |(k, _)| {
345+
if seen_keys.contains(k) { None }
346+
else { seen_keys.insert(*k); Some(*k) }
347+
});
348+
349+
// create (B): a mapping of keys to the last value seen for that key
350+
// this is the same as reversing the input and taking the first
351+
// value seen for that key!
352+
let mut last_val_per_key = HashMap::new();
353+
for &(k, v) in input.iter().rev() {
354+
if !last_val_per_key.contains_key(&k) {
355+
last_val_per_key.insert(k, v);
356+
}
357+
}
358+
359+
// iterate over the keys in (A) in order, and match each one with
360+
// the corresponding last value from (B)
361+
let mut ans: Vec<_> = unique_keys_forward
362+
.map(|k| (k, *last_val_per_key.get(&k).unwrap()))
363+
.collect();
364+
365+
// finally, since this test is testing `.reverse()`, reverse the
366+
// answer in-place
367+
ans.reverse();
368+
369+
ans
370+
}
371+
372+
let answer = generate_answer(&keyvals.0);
373+
374+
// perform the work
375+
map.reverse();
376+
377+
// check it contains all the values it should
378+
for &(key, val) in &answer {
379+
assert_eq!(map[&key], val);
380+
}
381+
382+
// check the order
383+
let mapv = Vec::from_iter(map);
384+
assert_eq!(answer, mapv);
385+
}
333386
}
334387

335388
fn assert_sorted_by_key<I, Key, X>(iterable: I, key: Key)

0 commit comments

Comments
 (0)