@@ -664,13 +664,59 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> {
664
664
replace ( self . get_mut ( ) , value)
665
665
}
666
666
667
+ #[ deprecated( note = "use `swap_remove` or `shift_remove`" ) ]
667
668
pub fn remove ( self ) -> V {
668
- self . remove_entry ( ) . 1
669
+ self . swap_remove ( )
670
+ }
671
+
672
+ /// Remove the key, value pair stored in the map for this entry, and return the value.
673
+ ///
674
+ /// Like `Vec::swap_remove`, the pair is removed by swapping it with the
675
+ /// last element of the map and popping it off. **This perturbs
676
+ /// the postion of what used to be the last element!**
677
+ ///
678
+ /// Computes in **O(1)** time (average).
679
+ pub fn swap_remove ( self ) -> V {
680
+ self . swap_remove_entry ( ) . 1
681
+ }
682
+
683
+ /// Remove the key, value pair stored in the map for this entry, and return the value.
684
+ ///
685
+ /// Like `Vec::remove`, the pair is removed by shifting all of the
686
+ /// elements that follow it, preserving their relative order.
687
+ /// **This perturbs the index of all of those elements!**
688
+ ///
689
+ /// Computes in **O(n)** time (average).
690
+ pub fn shift_remove ( self ) -> V {
691
+ self . shift_remove_entry ( ) . 1
669
692
}
670
693
671
694
/// Remove and return the key, value pair stored in the map for this entry
695
+ #[ deprecated( note = "use `swap_remove_entry` or `shift_remove_entry`" ) ]
672
696
pub fn remove_entry ( self ) -> ( K , V ) {
673
- self . map . remove_found ( self . probe , self . index )
697
+ self . swap_remove_entry ( )
698
+ }
699
+
700
+ /// Remove and return the key, value pair stored in the map for this entry
701
+ ///
702
+ /// Like `Vec::swap_remove`, the pair is removed by swapping it with the
703
+ /// last element of the map and popping it off. **This perturbs
704
+ /// the postion of what used to be the last element!**
705
+ ///
706
+ /// Computes in **O(1)** time (average).
707
+ pub fn swap_remove_entry ( self ) -> ( K , V ) {
708
+ self . map . swap_remove_found ( self . probe , self . index )
709
+ }
710
+
711
+ /// Remove and return the key, value pair stored in the map for this entry
712
+ ///
713
+ /// Like `Vec::remove`, the pair is removed by shifting all of the
714
+ /// elements that follow it, preserving their relative order.
715
+ /// **This perturbs the index of all of those elements!**
716
+ ///
717
+ /// Computes in **O(n)** time (average).
718
+ pub fn shift_remove_entry ( self ) -> ( K , V ) {
719
+ self . map . shift_remove_found ( self . probe , self . index )
674
720
}
675
721
}
676
722
@@ -955,6 +1001,7 @@ impl<K, V, S> IndexMap<K, V, S>
955
1001
/// NOTE: Same as .swap_remove
956
1002
///
957
1003
/// Computes in **O(1)** time (average).
1004
+ #[ deprecated( note = "use `swap_remove`" ) ]
958
1005
pub fn remove < Q : ?Sized > ( & mut self , key : & Q ) -> Option < V >
959
1006
where Q : Hash + Equivalent < K > ,
960
1007
{
@@ -985,14 +1032,53 @@ impl<K, V, S> IndexMap<K, V, S>
985
1032
/// the postion of what used to be the last element!**
986
1033
///
987
1034
/// Return `None` if `key` is not in map.
1035
+ ///
1036
+ /// Computes in **O(1)** time (average).
988
1037
pub fn swap_remove_full < Q : ?Sized > ( & mut self , key : & Q ) -> Option < ( usize , K , V ) >
989
1038
where Q : Hash + Equivalent < K > ,
990
1039
{
991
1040
let ( probe, found) = match self . find ( key) {
992
1041
None => return None ,
993
1042
Some ( t) => t,
994
1043
} ;
995
- let ( k, v) = self . core . remove_found ( probe, found) ;
1044
+ let ( k, v) = self . core . swap_remove_found ( probe, found) ;
1045
+ Some ( ( found, k, v) )
1046
+ }
1047
+
1048
+ /// Remove the key-value pair equivalent to `key` and return
1049
+ /// its value.
1050
+ ///
1051
+ /// Like `Vec::remove`, the pair is removed by shifting all of the
1052
+ /// elements that follow it, preserving their relative order.
1053
+ /// **This perturbs the index of all of those elements!**
1054
+ ///
1055
+ /// Return `None` if `key` is not in map.
1056
+ ///
1057
+ /// Computes in **O(n)** time (average).
1058
+ pub fn shift_remove < Q : ?Sized > ( & mut self , key : & Q ) -> Option < V >
1059
+ where Q : Hash + Equivalent < K > ,
1060
+ {
1061
+ self . shift_remove_full ( key) . map ( third)
1062
+ }
1063
+
1064
+ /// Remove the key-value pair equivalent to `key` and return it and
1065
+ /// the index it had.
1066
+ ///
1067
+ /// Like `Vec::remove`, the pair is removed by shifting all of the
1068
+ /// elements that follow it, preserving their relative order.
1069
+ /// **This perturbs the index of all of those elements!**
1070
+ ///
1071
+ /// Return `None` if `key` is not in map.
1072
+ ///
1073
+ /// Computes in **O(n)** time (average).
1074
+ pub fn shift_remove_full < Q : ?Sized > ( & mut self , key : & Q ) -> Option < ( usize , K , V ) >
1075
+ where Q : Hash + Equivalent < K > ,
1076
+ {
1077
+ let ( probe, found) = match self . find ( key) {
1078
+ None => return None ,
1079
+ Some ( t) => t,
1080
+ } ;
1081
+ let ( k, v) = self . core . shift_remove_found ( probe, found) ;
996
1082
Some ( ( found, k, v) )
997
1083
}
998
1084
@@ -1103,6 +1189,10 @@ impl<K, V, S> IndexMap<K, V, S> {
1103
1189
///
1104
1190
/// Valid indices are *0 <= index < self.len()*
1105
1191
///
1192
+ /// Like `Vec::swap_remove`, the pair is removed by swapping it with the
1193
+ /// last element of the map and popping it off. **This perturbs
1194
+ /// the postion of what used to be the last element!**
1195
+ ///
1106
1196
/// Computes in **O(1)** time (average).
1107
1197
pub fn swap_remove_index ( & mut self , index : usize ) -> Option < ( K , V ) > {
1108
1198
let ( probe, found) = match self . core . entries . get ( index)
@@ -1111,7 +1201,26 @@ impl<K, V, S> IndexMap<K, V, S> {
1111
1201
None => return None ,
1112
1202
Some ( t) => t,
1113
1203
} ;
1114
- Some ( self . core . remove_found ( probe, found) )
1204
+ Some ( self . core . swap_remove_found ( probe, found) )
1205
+ }
1206
+
1207
+ /// Remove the key-value pair by index
1208
+ ///
1209
+ /// Valid indices are *0 <= index < self.len()*
1210
+ ///
1211
+ /// Like `Vec::remove`, the pair is removed by shifting all of the
1212
+ /// elements that follow it, preserving their relative order.
1213
+ /// **This perturbs the index of all of those elements!**
1214
+ ///
1215
+ /// Computes in **O(n)** time (average).
1216
+ pub fn shift_remove_index ( & mut self , index : usize ) -> Option < ( K , V ) > {
1217
+ let ( probe, found) = match self . core . entries . get ( index)
1218
+ . map ( |e| self . core . find_existing_entry ( e) )
1219
+ {
1220
+ None => return None ,
1221
+ Some ( t) => t,
1222
+ } ;
1223
+ Some ( self . core . shift_remove_found ( probe, found) )
1115
1224
}
1116
1225
}
1117
1226
@@ -1225,7 +1334,7 @@ impl<K, V> OrderMapCore<K, V> {
1225
1334
Some ( t) => t,
1226
1335
} ;
1227
1336
debug_assert_eq ! ( found, self . entries. len( ) - 1 ) ;
1228
- Some ( self . remove_found ( probe, found) )
1337
+ Some ( self . swap_remove_found ( probe, found) )
1229
1338
}
1230
1339
1231
1340
// FIXME: reduce duplication (compare with insert)
@@ -1375,11 +1484,61 @@ impl<K, V> OrderMapCore<K, V> {
1375
1484
( probe, actual_pos)
1376
1485
}
1377
1486
1378
- fn remove_found ( & mut self , probe : usize , found : usize ) -> ( K , V ) {
1379
- dispatch_32_vs_64 ! ( self . remove_found_impl( probe, found) )
1487
+ /// Remove an entry by shifting all entries that follow it
1488
+ fn shift_remove_found ( & mut self , probe : usize , found : usize ) -> ( K , V ) {
1489
+ dispatch_32_vs_64 ! ( self . shift_remove_found_impl( probe, found) )
1490
+ }
1491
+
1492
+ fn shift_remove_found_impl < Sz > ( & mut self , probe : usize , found : usize ) -> ( K , V )
1493
+ where Sz : Size
1494
+ {
1495
+ // index `probe` and entry `found` is to be removed
1496
+ // use Vec::remove, but then we need to update the indices that point
1497
+ // to all of the other entries that have to move
1498
+ self . indices [ probe] = Pos :: none ( ) ;
1499
+ let entry = self . entries . remove ( found) ;
1500
+
1501
+ // correct indices that point to the entries that followed the removed entry.
1502
+ // use a heuristic between a full sweep vs. a `probe_loop!` for every shifted item.
1503
+ if self . indices . len ( ) < ( self . entries . len ( ) - found) * 2 {
1504
+ // shift all indices greater than `found`
1505
+ for pos in self . indices . iter_mut ( ) {
1506
+ if let Some ( ( i, _) ) = pos. resolve :: < Sz > ( ) {
1507
+ if i > found {
1508
+ // shift the index
1509
+ pos. set_pos :: < Sz > ( i - 1 ) ;
1510
+ }
1511
+ }
1512
+ }
1513
+ } else {
1514
+ // find each following entry to shift its index
1515
+ for ( offset, entry) in enumerate ( & self . entries [ found..] ) {
1516
+ let index = found + offset;
1517
+ let mut probe = desired_pos ( self . mask , entry. hash ) ;
1518
+ probe_loop ! ( probe < self . indices. len( ) , {
1519
+ let pos = & mut self . indices[ probe] ;
1520
+ if let Some ( ( i, _) ) = pos. resolve:: <Sz >( ) {
1521
+ if i == index + 1 {
1522
+ // found it, shift it
1523
+ pos. set_pos:: <Sz >( index) ;
1524
+ break ;
1525
+ }
1526
+ }
1527
+ } ) ;
1528
+ }
1529
+ }
1530
+
1531
+ self . backward_shift_after_removal :: < Sz > ( probe) ;
1532
+
1533
+ ( entry. key , entry. value )
1534
+ }
1535
+
1536
+ /// Remove an entry by swapping it with the last
1537
+ fn swap_remove_found ( & mut self , probe : usize , found : usize ) -> ( K , V ) {
1538
+ dispatch_32_vs_64 ! ( self . swap_remove_found_impl( probe, found) )
1380
1539
}
1381
1540
1382
- fn remove_found_impl < Sz > ( & mut self , probe : usize , found : usize ) -> ( K , V )
1541
+ fn swap_remove_found_impl < Sz > ( & mut self , probe : usize , found : usize ) -> ( K , V )
1383
1542
where Sz : Size
1384
1543
{
1385
1544
// index `probe` and entry `found` is to be removed
@@ -1394,10 +1553,11 @@ impl<K, V> OrderMapCore<K, V> {
1394
1553
// examine new element in `found` and find it in indices
1395
1554
let mut probe = desired_pos ( self . mask , entry. hash ) ;
1396
1555
probe_loop ! ( probe < self . indices. len( ) , {
1397
- if let Some ( ( i, _) ) = self . indices[ probe] . resolve:: <Sz >( ) {
1556
+ let pos = & mut self . indices[ probe] ;
1557
+ if let Some ( ( i, _) ) = pos. resolve:: <Sz >( ) {
1398
1558
if i >= self . entries. len( ) {
1399
1559
// found it
1400
- self . indices [ probe ] = Pos :: with_hash :: <Sz >( found, entry . hash ) ;
1560
+ pos . set_pos :: <Sz >( found) ;
1401
1561
break ;
1402
1562
}
1403
1563
}
@@ -2151,7 +2311,7 @@ mod tests {
2151
2311
map_a. insert ( 2 , "2" ) ;
2152
2312
let mut map_b = map_a. clone ( ) ;
2153
2313
assert_eq ! ( map_a, map_b) ;
2154
- map_b. remove ( & 1 ) ;
2314
+ map_b. swap_remove ( & 1 ) ;
2155
2315
assert_ne ! ( map_a, map_b) ;
2156
2316
2157
2317
let map_c: IndexMap < _ , String > = map_b. into_iter ( ) . map ( |( k, v) | ( k, v. to_owned ( ) ) ) . collect ( ) ;
0 commit comments