Skip to content

Commit e844b52

Browse files
committed
auto merge of #7806 : apasel422/rust/hash_consume, r=catamorphism
This partially addresses #7719.
2 parents 04f9ce0 + faa280c commit e844b52

File tree

1 file changed

+82
-0
lines changed

1 file changed

+82
-0
lines changed

src/libstd/hashmap.rs

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,14 @@ impl<K: Hash + Eq, V> HashMap<K, V> {
455455
}
456456
}
457457

458+
/// Creates a consuming iterator, that is, one that moves each key-value
459+
/// pair out of the map in arbitrary order. The map cannot be used after
460+
/// calling this.
461+
pub fn consume_iter(self) -> HashMapConsumeIterator<K, V> {
462+
// `consume_rev_iter` is more efficient than `consume_iter` for vectors
463+
HashMapConsumeIterator {iter: self.buckets.consume_rev_iter()}
464+
}
465+
458466
/// Retrieves a value for the given key, failing if the key is not
459467
/// present.
460468
pub fn get<'a>(&'a self, k: &K) -> &'a V {
@@ -568,11 +576,21 @@ pub struct HashMapMutIterator<'self, K, V> {
568576
priv iter: vec::VecMutIterator<'self, Option<Bucket<K, V>>>,
569577
}
570578

579+
/// HashMap consume iterator
580+
pub struct HashMapConsumeIterator<K, V> {
581+
priv iter: vec::VecConsumeRevIterator<Option<Bucket<K, V>>>,
582+
}
583+
571584
/// HashSet iterator
572585
pub struct HashSetIterator<'self, K> {
573586
priv iter: vec::VecIterator<'self, Option<Bucket<K, ()>>>,
574587
}
575588

589+
/// HashSet consume iterator
590+
pub struct HashSetConsumeIterator<K> {
591+
priv iter: vec::VecConsumeRevIterator<Option<Bucket<K, ()>>>,
592+
}
593+
576594
impl<'self, K, V> Iterator<(&'self K, &'self V)> for HashMapIterator<'self, K, V> {
577595
#[inline]
578596
fn next(&mut self) -> Option<(&'self K, &'self V)> {
@@ -599,6 +617,19 @@ impl<'self, K, V> Iterator<(&'self K, &'self mut V)> for HashMapMutIterator<'sel
599617
}
600618
}
601619

620+
impl<K, V> Iterator<(K, V)> for HashMapConsumeIterator<K, V> {
621+
#[inline]
622+
fn next(&mut self) -> Option<(K, V)> {
623+
for self.iter.advance |elt| {
624+
match elt {
625+
Some(Bucket {key, value, _}) => return Some((key, value)),
626+
None => {},
627+
}
628+
}
629+
None
630+
}
631+
}
632+
602633
impl<'self, K> Iterator<&'self K> for HashSetIterator<'self, K> {
603634
#[inline]
604635
fn next(&mut self) -> Option<&'self K> {
@@ -612,6 +643,19 @@ impl<'self, K> Iterator<&'self K> for HashSetIterator<'self, K> {
612643
}
613644
}
614645

646+
impl<K> Iterator<K> for HashSetConsumeIterator<K> {
647+
#[inline]
648+
fn next(&mut self) -> Option<K> {
649+
for self.iter.advance |elt| {
650+
match elt {
651+
Some(bucket) => return Some(bucket.key),
652+
None => {},
653+
}
654+
}
655+
None
656+
}
657+
}
658+
615659
impl<K: Eq + Hash, V, T: Iterator<(K, V)>> FromIterator<(K, V), T> for HashMap<K, V> {
616660
pub fn from_iterator(iter: &mut T) -> HashMap<K, V> {
617661
let (lower, _) = iter.size_hint();
@@ -726,6 +770,14 @@ impl<T:Hash + Eq> HashSet<T> {
726770
self.map.consume(|k, _| f(k))
727771
}
728772

773+
/// Creates a consuming iterator, that is, one that moves each value out
774+
/// of the set in arbitrary order. The set cannot be used after calling
775+
/// this.
776+
pub fn consume_iter(self) -> HashSetConsumeIterator<T> {
777+
// `consume_rev_iter` is more efficient than `consume_iter` for vectors
778+
HashSetConsumeIterator {iter: self.map.buckets.consume_rev_iter()}
779+
}
780+
729781
/// Returns true if the hash set contains a value equivalent to the
730782
/// given query value.
731783
pub fn contains_equiv<Q:Hash + Equiv<T>>(&self, value: &Q) -> bool {
@@ -888,6 +940,21 @@ mod test_map {
888940
assert!(m.insert(1, 2));
889941
}
890942

943+
#[test]
944+
fn test_consume_iter() {
945+
let hm = {
946+
let mut hm = HashMap::new();
947+
948+
hm.insert('a', 1);
949+
hm.insert('b', 2);
950+
951+
hm
952+
};
953+
954+
let v = hm.consume_iter().collect::<~[(char, int)]>();
955+
assert!([('a', 1), ('b', 2)] == v || [('b', 2), ('a', 1)] == v);
956+
}
957+
891958
#[test]
892959
fn test_iterate() {
893960
let mut m = linear_map_with_capacity(4);
@@ -1168,4 +1235,19 @@ mod test_set {
11681235
assert!(set.contains(x));
11691236
}
11701237
}
1238+
1239+
#[test]
1240+
fn test_consume_iter() {
1241+
let hs = {
1242+
let mut hs = HashSet::new();
1243+
1244+
hs.insert('a');
1245+
hs.insert('b');
1246+
1247+
hs
1248+
};
1249+
1250+
let v = hs.consume_iter().collect::<~[char]>();
1251+
assert!(['a', 'b'] == v || ['b', 'a'] == v);
1252+
}
11711253
}

0 commit comments

Comments
 (0)