Skip to content

Commit feb816c

Browse files
committed
Add a replace_full method on IndexSet
* Add a new `replace_full` method, which behaves like `replace` but also returns the index of the item. * Clarify that `replace` and `replace_all` do not modify the replaced item's insertion order in the documentation. * Add test coverage for `replace` and `replace_full` by copying the existing tests for `insert` and `insert_full`.
1 parent d6a9dd6 commit feb816c

File tree

1 file changed

+120
-3
lines changed

1 file changed

+120
-3
lines changed

src/set.rs

+120-3
Original file line numberDiff line numberDiff line change
@@ -396,18 +396,29 @@ where
396396
}
397397

398398
/// Adds a value to the set, replacing the existing value, if any, that is
399-
/// equal to the given one. Returns the replaced value.
399+
/// equal to the given one, without altering its insertion order. Returns
400+
/// the replaced value.
400401
///
401402
/// Computes in **O(1)** time (average).
402403
pub fn replace(&mut self, value: T) -> Option<T> {
404+
self.replace_full(value).1
405+
}
406+
407+
/// Adds a value to the set, replacing the existing value, if any, that is
408+
/// equal to the given one, without altering its insertion order. Returns
409+
/// the index of the item and its replaced value.
410+
///
411+
/// Computes in **O(1)** time (average).
412+
pub fn replace_full(&mut self, value: T) -> (usize, Option<T>) {
403413
use super::map::Entry::*;
404414

405415
match self.map.entry(value) {
406416
Vacant(e) => {
417+
let index = e.index();
407418
e.insert(());
408-
None
419+
(index, None)
409420
}
410-
Occupied(e) => Some(e.replace_key()),
421+
Occupied(e) => (e.index(), Some(e.replace_key())),
411422
}
412423
}
413424

@@ -1484,6 +1495,112 @@ mod tests {
14841495
}
14851496
}
14861497

1498+
#[test]
1499+
fn replace() {
1500+
let replace = [0, 4, 2, 12, 8, 7, 11, 5];
1501+
let not_present = [1, 3, 6, 9, 10];
1502+
let mut set = IndexSet::with_capacity(replace.len());
1503+
1504+
for (i, &elt) in enumerate(&replace) {
1505+
assert_eq!(set.len(), i);
1506+
set.replace(elt);
1507+
assert_eq!(set.len(), i + 1);
1508+
assert_eq!(set.get(&elt), Some(&elt));
1509+
}
1510+
println!("{:?}", set);
1511+
1512+
for &elt in &not_present {
1513+
assert!(set.get(&elt).is_none());
1514+
}
1515+
}
1516+
1517+
#[test]
1518+
fn replace_full() {
1519+
let replace = vec![9, 2, 7, 1, 4, 6, 13];
1520+
let present = vec![1, 6, 2];
1521+
let mut set = IndexSet::with_capacity(replace.len());
1522+
1523+
for (i, &elt) in enumerate(&replace) {
1524+
assert_eq!(set.len(), i);
1525+
let (index, replaced) = set.replace_full(elt);
1526+
assert!(replaced.is_none());
1527+
assert_eq!(Some(index), set.get_full(&elt).map(|x| x.0));
1528+
assert_eq!(set.len(), i + 1);
1529+
}
1530+
1531+
let len = set.len();
1532+
for &elt in &present {
1533+
let (index, replaced) = set.replace_full(elt);
1534+
assert_eq!(Some(elt), replaced);
1535+
assert_eq!(Some(index), set.get_full(&elt).map(|x| x.0));
1536+
assert_eq!(set.len(), len);
1537+
}
1538+
}
1539+
1540+
#[test]
1541+
fn replace_2() {
1542+
let mut set = IndexSet::with_capacity(16);
1543+
1544+
let mut values = vec![];
1545+
values.extend(0..16);
1546+
values.extend(if cfg!(miri) { 32..64 } else { 128..267 });
1547+
1548+
for &i in &values {
1549+
let old_set = set.clone();
1550+
set.replace(i);
1551+
for value in old_set.iter() {
1552+
if set.get(value).is_none() {
1553+
println!("old_set: {:?}", old_set);
1554+
println!("set: {:?}", set);
1555+
panic!("did not find {} in set", value);
1556+
}
1557+
}
1558+
}
1559+
1560+
for &i in &values {
1561+
assert!(set.get(&i).is_some(), "did not find {}", i);
1562+
}
1563+
}
1564+
1565+
#[test]
1566+
fn replace_dup() {
1567+
let mut elements = vec![0, 2, 4, 6, 8];
1568+
let mut set: IndexSet<u8> = elements.drain(..).collect();
1569+
{
1570+
let (i, v) = set.get_full(&0).unwrap();
1571+
assert_eq!(set.len(), 5);
1572+
assert_eq!(i, 0);
1573+
assert_eq!(*v, 0);
1574+
}
1575+
{
1576+
let replaced = set.replace(0);
1577+
let (i, v) = set.get_full(&0).unwrap();
1578+
assert_eq!(set.len(), 5);
1579+
assert_eq!(replaced, Some(0));
1580+
assert_eq!(i, 0);
1581+
assert_eq!(*v, 0);
1582+
}
1583+
}
1584+
1585+
#[test]
1586+
fn replace_order() {
1587+
let replace = [0, 4, 2, 12, 8, 7, 11, 5, 3, 17, 19, 22, 23];
1588+
let mut set = IndexSet::new();
1589+
1590+
for &elt in &replace {
1591+
set.replace(elt);
1592+
}
1593+
1594+
assert_eq!(set.iter().count(), set.len());
1595+
assert_eq!(set.iter().count(), replace.len());
1596+
for (a, b) in replace.iter().zip(set.iter()) {
1597+
assert_eq!(a, b);
1598+
}
1599+
for (i, v) in (0..replace.len()).zip(set.iter()) {
1600+
assert_eq!(set.get_index(i).unwrap(), v);
1601+
}
1602+
}
1603+
14871604
#[test]
14881605
fn grow() {
14891606
let insert = [0, 4, 2, 12, 8, 7, 11];

0 commit comments

Comments
 (0)