Skip to content

Commit 47ba458

Browse files
committed
auto merge of #7815 : blake2-ppc/rust/hashmap-iterators, r=huonw
Implement set difference, sym. difference, intersection and union using Iterators. The set methods are left since they are part of the Set trait. A grep over the tree indicates that the four hashset operations have no users at all. Also remove HashMap::mutate_values since it is unused, replaced by .mut_iter(), and not part of a trait.
2 parents 98c1654 + 750f32d commit 47ba458

File tree

1 file changed

+70
-23
lines changed

1 file changed

+70
-23
lines changed

src/libstd/hashmap.rs

+70-23
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,10 @@
1616
#[mutable_doc];
1717

1818
use container::{Container, Mutable, Map, MutableMap, Set, MutableSet};
19+
use clone::Clone;
1920
use cmp::{Eq, Equiv};
2021
use hash::Hash;
21-
use iterator::{Iterator, IteratorUtil, FromIterator};
22+
use iterator::{Iterator, IteratorUtil, FromIterator, ChainIterator};
2223
use num;
2324
use option::{None, Option, Some};
2425
use rand::RngUtil;
@@ -510,19 +511,6 @@ impl<K: Hash + Eq, V> HashMap<K, V> {
510511
self.iter().advance(|(_, v)| blk(v))
511512
}
512513

513-
/// Iterate over the map and mutate the contained values
514-
pub fn mutate_values(&mut self, blk: &fn(&K, &mut V) -> bool) -> bool {
515-
for uint::range(0, self.buckets.len()) |i| {
516-
match self.buckets[i] {
517-
Some(Bucket{key: ref key, value: ref mut value, _}) => {
518-
if !blk(key, value) { return false; }
519-
}
520-
None => ()
521-
}
522-
}
523-
return true;
524-
}
525-
526514
/// An iterator visiting all key-value pairs in arbitrary order.
527515
/// Iterator element type is (&'a K, &'a V).
528516
pub fn iter<'a>(&'a self) -> HashMapIterator<'a, K, V> {
@@ -716,25 +704,24 @@ impl<T:Hash + Eq> Set<T> for HashSet<T> {
716704

717705
/// Visit the values representing the difference
718706
fn difference(&self, other: &HashSet<T>, f: &fn(&T) -> bool) -> bool {
719-
self.iter().advance(|v| other.contains(v) || f(v))
707+
self.difference_iter(other).advance(f)
720708
}
721709

722710
/// Visit the values representing the symmetric difference
723711
fn symmetric_difference(&self,
724712
other: &HashSet<T>,
725713
f: &fn(&T) -> bool) -> bool {
726-
self.difference(other, |t| f(t)) && other.difference(self, |t| f(t))
714+
self.symmetric_difference_iter(other).advance(f)
727715
}
728716

729717
/// Visit the values representing the intersection
730718
fn intersection(&self, other: &HashSet<T>, f: &fn(&T) -> bool) -> bool {
731-
self.iter().advance(|v| !other.contains(v) || f(v))
719+
self.intersection_iter(other).advance(f)
732720
}
733721

734722
/// Visit the values representing the union
735723
fn union(&self, other: &HashSet<T>, f: &fn(&T) -> bool) -> bool {
736-
self.iter().advance(|t| f(t)) &&
737-
other.iter().advance(|v| self.contains(v) || f(v))
724+
self.union_iter(other).advance(f)
738725
}
739726
}
740727

@@ -789,6 +776,33 @@ impl<T:Hash + Eq> HashSet<T> {
789776
pub fn iter<'a>(&'a self) -> HashSetIterator<'a, T> {
790777
HashSetIterator { iter: self.map.buckets.iter() }
791778
}
779+
780+
/// Visit the values representing the difference
781+
pub fn difference_iter<'a>(&'a self, other: &'a HashSet<T>)
782+
-> SetAlgebraIter<'a, T> {
783+
EnvFilterIterator{iter: self.iter(), env: other,
784+
filter: |elt, other| !other.contains(elt) }
785+
}
786+
787+
/// Visit the values representing the symmetric difference
788+
pub fn symmetric_difference_iter<'a>(&'a self, other: &'a HashSet<T>)
789+
-> ChainIterator<&'a T, SetAlgebraIter<'a, T>, SetAlgebraIter<'a, T>> {
790+
self.difference_iter(other).chain_(other.difference_iter(self))
791+
}
792+
793+
/// Visit the values representing the intersection
794+
pub fn intersection_iter<'a>(&'a self, other: &'a HashSet<T>)
795+
-> SetAlgebraIter<'a, T> {
796+
EnvFilterIterator{iter: self.iter(), env: other,
797+
filter: |elt, other| other.contains(elt) }
798+
}
799+
800+
/// Visit the values representing the union
801+
pub fn union_iter<'a>(&'a self, other: &'a HashSet<T>)
802+
-> ChainIterator<&'a T, HashSetIterator<'a, T>, SetAlgebraIter<'a, T>> {
803+
self.iter().chain_(other.difference_iter(self))
804+
}
805+
792806
}
793807

794808
impl<K: Eq + Hash, T: Iterator<K>> FromIterator<K, T> for HashSet<K> {
@@ -804,6 +818,39 @@ impl<K: Eq + Hash, T: Iterator<K>> FromIterator<K, T> for HashSet<K> {
804818
}
805819
}
806820

821+
// FIXME #7814: use std::iterator::FilterIterator
822+
/// Building block for Set operation iterators
823+
pub struct EnvFilterIterator<A, Env, I> {
824+
priv env: Env,
825+
priv filter: &'static fn(&A, Env) -> bool,
826+
priv iter: I,
827+
}
828+
829+
impl<'self, A, Env: Clone, I: Iterator<&'self A>> Iterator<&'self A>
830+
for EnvFilterIterator<A, Env, I> {
831+
#[inline]
832+
fn next(&mut self) -> Option<&'self A> {
833+
loop {
834+
match self.iter.next() {
835+
Some(elt) => if (self.filter)(elt, self.env.clone()) {
836+
return Some(elt)
837+
},
838+
None => return None,
839+
}
840+
}
841+
}
842+
843+
#[inline]
844+
fn size_hint(&self) -> (uint, Option<uint>) {
845+
let (_, upper) = self.iter.size_hint();
846+
(0, upper)
847+
}
848+
}
849+
850+
/// Set operations iterator
851+
pub type SetAlgebraIter<'self, T> =
852+
EnvFilterIterator<T, &'self HashSet<T>, HashSetIterator<'self, T>>;
853+
807854

808855
#[cfg(test)]
809856
mod test_map {
@@ -1139,7 +1186,7 @@ mod test_set {
11391186

11401187
let mut i = 0;
11411188
let expected = [3, 5, 11, 77];
1142-
for a.intersection(&b) |x| {
1189+
for a.intersection_iter(&b).advance |x| {
11431190
assert!(expected.contains(x));
11441191
i += 1
11451192
}
@@ -1162,7 +1209,7 @@ mod test_set {
11621209

11631210
let mut i = 0;
11641211
let expected = [1, 5, 11];
1165-
for a.difference(&b) |x| {
1212+
for a.difference_iter(&b).advance |x| {
11661213
assert!(expected.contains(x));
11671214
i += 1
11681215
}
@@ -1188,7 +1235,7 @@ mod test_set {
11881235

11891236
let mut i = 0;
11901237
let expected = [-2, 1, 5, 11, 14, 22];
1191-
for a.symmetric_difference(&b) |x| {
1238+
for a.symmetric_difference_iter(&b).advance |x| {
11921239
assert!(expected.contains(x));
11931240
i += 1
11941241
}
@@ -1218,7 +1265,7 @@ mod test_set {
12181265

12191266
let mut i = 0;
12201267
let expected = [-2, 1, 3, 5, 9, 11, 13, 16, 19, 24];
1221-
for a.union(&b) |x| {
1268+
for a.union_iter(&b).advance |x| {
12221269
assert!(expected.contains(x));
12231270
i += 1
12241271
}

0 commit comments

Comments
 (0)