mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-28 09:44:08 +00:00
auto merge of #7319 : thestinger/rust/hashmap-iterator, r=thestinger
#7277
This commit is contained in:
commit
cb58b19f02
@ -18,15 +18,13 @@
|
|||||||
use container::{Container, Mutable, Map, Set};
|
use container::{Container, Mutable, Map, Set};
|
||||||
use cmp::{Eq, Equiv};
|
use cmp::{Eq, Equiv};
|
||||||
use hash::Hash;
|
use hash::Hash;
|
||||||
use old_iter::BaseIter;
|
use iterator::{Iterator, IteratorUtil};
|
||||||
use old_iter;
|
|
||||||
use iterator::IteratorUtil;
|
|
||||||
use option::{None, Option, Some};
|
use option::{None, Option, Some};
|
||||||
use rand::RngUtil;
|
use rand::RngUtil;
|
||||||
use rand;
|
use rand;
|
||||||
use uint;
|
use uint;
|
||||||
use vec;
|
use vec;
|
||||||
use vec::ImmutableVector;
|
use vec::{ImmutableVector, MutableVector};
|
||||||
use kinds::Copy;
|
use kinds::Copy;
|
||||||
use util::{replace, unreachable};
|
use util::{replace, unreachable};
|
||||||
|
|
||||||
@ -311,24 +309,17 @@ impl<K:Hash + Eq,V> Map<K, V> for HashMap<K, V> {
|
|||||||
|
|
||||||
/// Visit all key-value pairs
|
/// Visit all key-value pairs
|
||||||
fn each<'a>(&'a self, blk: &fn(&K, &'a V) -> bool) -> bool {
|
fn each<'a>(&'a self, blk: &fn(&K, &'a V) -> bool) -> bool {
|
||||||
for self.buckets.iter().advance |bucket| {
|
self.iter().advance(|(k, v)| blk(k, v))
|
||||||
for bucket.iter().advance |pair| {
|
|
||||||
if !blk(&pair.key, &pair.value) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Visit all keys
|
/// Visit all keys
|
||||||
fn each_key(&self, blk: &fn(k: &K) -> bool) -> bool {
|
fn each_key(&self, blk: &fn(k: &K) -> bool) -> bool {
|
||||||
self.each(|k, _| blk(k))
|
self.iter().advance(|(k, _)| blk(k))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Visit all values
|
/// Visit all values
|
||||||
fn each_value<'a>(&'a self, blk: &fn(v: &'a V) -> bool) -> bool {
|
fn each_value<'a>(&'a self, blk: &fn(v: &'a V) -> bool) -> bool {
|
||||||
self.each(|_, v| blk(v))
|
self.iter().advance(|(_, v)| blk(v))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Iterate over the map and mutate the contained values
|
/// Iterate over the map and mutate the contained values
|
||||||
@ -524,6 +515,19 @@ impl<K: Hash + Eq, V> HashMap<K, V> {
|
|||||||
TableFull | FoundHole(_) => None,
|
TableFull | FoundHole(_) => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An iterator visiting all key-value pairs in arbitrary order.
|
||||||
|
/// Iterator element type is (&'a K, &'a V).
|
||||||
|
pub fn iter<'a>(&'a self) -> HashMapIterator<'a, K, V> {
|
||||||
|
HashMapIterator { iter: self.buckets.iter() }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// An iterator visiting all key-value pairs in arbitrary order,
|
||||||
|
/// with mutable references to the values.
|
||||||
|
/// Iterator element type is (&'a K, &'a mut V).
|
||||||
|
pub fn mut_iter<'a>(&'a mut self) -> HashMapMutIterator<'a, K, V> {
|
||||||
|
HashMapMutIterator { iter: self.buckets.mut_iter() }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<K: Hash + Eq, V: Copy> HashMap<K, V> {
|
impl<K: Hash + Eq, V: Copy> HashMap<K, V> {
|
||||||
@ -542,7 +546,7 @@ impl<K:Hash + Eq,V:Eq> Eq for HashMap<K, V> {
|
|||||||
fn eq(&self, other: &HashMap<K, V>) -> bool {
|
fn eq(&self, other: &HashMap<K, V>) -> bool {
|
||||||
if self.len() != other.len() { return false; }
|
if self.len() != other.len() { return false; }
|
||||||
|
|
||||||
for self.each |key, value| {
|
for self.iter().advance |(key, value)| {
|
||||||
match other.find(key) {
|
match other.find(key) {
|
||||||
None => return false,
|
None => return false,
|
||||||
Some(v) => if value != v { return false },
|
Some(v) => if value != v { return false },
|
||||||
@ -555,6 +559,61 @@ impl<K:Hash + Eq,V:Eq> Eq for HashMap<K, V> {
|
|||||||
fn ne(&self, other: &HashMap<K, V>) -> bool { !self.eq(other) }
|
fn ne(&self, other: &HashMap<K, V>) -> bool { !self.eq(other) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// HashMap iterator
|
||||||
|
pub struct HashMapIterator<'self, K, V> {
|
||||||
|
priv iter: vec::VecIterator<'self, Option<Bucket<K, V>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// HashMap mutable values iterator
|
||||||
|
pub struct HashMapMutIterator<'self, K, V> {
|
||||||
|
priv iter: vec::VecMutIterator<'self, Option<Bucket<K, V>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// HashSet iterator
|
||||||
|
pub struct HashSetIterator<'self, K> {
|
||||||
|
priv iter: vec::VecIterator<'self, Option<Bucket<K, ()>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'self, K, V> Iterator<(&'self K, &'self V)> for HashMapIterator<'self, K, V> {
|
||||||
|
#[inline]
|
||||||
|
fn next(&mut self) -> Option<(&'self K, &'self V)> {
|
||||||
|
for self.iter.advance |elt| {
|
||||||
|
match elt {
|
||||||
|
&Some(ref bucket) => return Some((&bucket.key, &bucket.value)),
|
||||||
|
&None => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'self, K, V> Iterator<(&'self K, &'self mut V)> for HashMapMutIterator<'self, K, V> {
|
||||||
|
#[inline]
|
||||||
|
fn next(&mut self) -> Option<(&'self K, &'self mut V)> {
|
||||||
|
for self.iter.advance |elt| {
|
||||||
|
match elt {
|
||||||
|
&Some(ref mut bucket) => return Some((&bucket.key, &mut bucket.value)),
|
||||||
|
&None => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'self, K> Iterator<&'self K> for HashSetIterator<'self, K> {
|
||||||
|
#[inline]
|
||||||
|
fn next(&mut self) -> Option<&'self K> {
|
||||||
|
for self.iter.advance |elt| {
|
||||||
|
match elt {
|
||||||
|
&Some(ref bucket) => return Some(&bucket.key),
|
||||||
|
&None => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// An implementation of a hash set using the underlying representation of a
|
/// An implementation of a hash set using the underlying representation of a
|
||||||
/// HashMap where the value is (). As with the `HashMap` type, a `HashSet`
|
/// HashMap where the value is (). As with the `HashMap` type, a `HashSet`
|
||||||
/// requires that the elements implement the `Eq` and `Hash` traits.
|
/// requires that the elements implement the `Eq` and `Hash` traits.
|
||||||
@ -562,12 +621,6 @@ pub struct HashSet<T> {
|
|||||||
priv map: HashMap<T, ()>
|
priv map: HashMap<T, ()>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T:Hash + Eq> BaseIter<T> for HashSet<T> {
|
|
||||||
/// Visit all values in order
|
|
||||||
fn each(&self, f: &fn(&T) -> bool) -> bool { self.map.each_key(f) }
|
|
||||||
fn size_hint(&self) -> Option<uint> { Some(self.len()) }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T:Hash + Eq> Eq for HashSet<T> {
|
impl<T:Hash + Eq> Eq for HashSet<T> {
|
||||||
fn eq(&self, other: &HashSet<T>) -> bool { self.map == other.map }
|
fn eq(&self, other: &HashSet<T>) -> bool { self.map == other.map }
|
||||||
fn ne(&self, other: &HashSet<T>) -> bool { self.map != other.map }
|
fn ne(&self, other: &HashSet<T>) -> bool { self.map != other.map }
|
||||||
@ -601,12 +654,12 @@ impl<T:Hash + Eq> Set<T> for HashSet<T> {
|
|||||||
/// Return true if the set has no elements in common with `other`.
|
/// Return true if the set has no elements in common with `other`.
|
||||||
/// This is equivalent to checking for an empty intersection.
|
/// This is equivalent to checking for an empty intersection.
|
||||||
fn is_disjoint(&self, other: &HashSet<T>) -> bool {
|
fn is_disjoint(&self, other: &HashSet<T>) -> bool {
|
||||||
old_iter::all(self, |v| !other.contains(v))
|
self.iter().all(|v| !other.contains(v))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return true if the set is a subset of another
|
/// Return true if the set is a subset of another
|
||||||
fn is_subset(&self, other: &HashSet<T>) -> bool {
|
fn is_subset(&self, other: &HashSet<T>) -> bool {
|
||||||
old_iter::all(self, |v| other.contains(v))
|
self.iter().all(|v| other.contains(v))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return true if the set is a superset of another
|
/// Return true if the set is a superset of another
|
||||||
@ -616,7 +669,7 @@ impl<T:Hash + Eq> Set<T> for HashSet<T> {
|
|||||||
|
|
||||||
/// Visit the values representing the difference
|
/// Visit the values representing the difference
|
||||||
fn difference(&self, other: &HashSet<T>, f: &fn(&T) -> bool) -> bool {
|
fn difference(&self, other: &HashSet<T>, f: &fn(&T) -> bool) -> bool {
|
||||||
self.each(|v| other.contains(v) || f(v))
|
self.iter().advance(|v| other.contains(v) || f(v))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Visit the values representing the symmetric difference
|
/// Visit the values representing the symmetric difference
|
||||||
@ -628,12 +681,12 @@ impl<T:Hash + Eq> Set<T> for HashSet<T> {
|
|||||||
|
|
||||||
/// Visit the values representing the intersection
|
/// Visit the values representing the intersection
|
||||||
fn intersection(&self, other: &HashSet<T>, f: &fn(&T) -> bool) -> bool {
|
fn intersection(&self, other: &HashSet<T>, f: &fn(&T) -> bool) -> bool {
|
||||||
self.each(|v| !other.contains(v) || f(v))
|
self.iter().advance(|v| !other.contains(v) || f(v))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Visit the values representing the union
|
/// Visit the values representing the union
|
||||||
fn union(&self, other: &HashSet<T>, f: &fn(&T) -> bool) -> bool {
|
fn union(&self, other: &HashSet<T>, f: &fn(&T) -> bool) -> bool {
|
||||||
self.each(f) && other.each(|v| self.contains(v) || f(v))
|
self.iter().advance(f) && other.iter().advance(|v| self.contains(v) || f(v))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -664,6 +717,18 @@ impl<T:Hash + Eq> HashSet<T> {
|
|||||||
pub fn contains_equiv<Q:Hash + Equiv<T>>(&self, value: &Q) -> bool {
|
pub fn contains_equiv<Q:Hash + Equiv<T>>(&self, value: &Q) -> bool {
|
||||||
self.map.contains_key_equiv(value)
|
self.map.contains_key_equiv(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Visit all elements in arbitrary order
|
||||||
|
/// FIXME: #6978: Remove when all callers are converted
|
||||||
|
pub fn each(&self, f: &fn(&T) -> bool) -> bool {
|
||||||
|
self.iter().advance(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// An iterator visiting all elements in arbitrary order.
|
||||||
|
/// Iterator element type is &'a T.
|
||||||
|
pub fn iter<'a>(&'a self) -> HashSetIterator<'a, T> {
|
||||||
|
HashSetIterator { iter: self.map.buckets.iter() }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@ -808,7 +873,7 @@ mod test_map {
|
|||||||
assert!(m.insert(i, i*2));
|
assert!(m.insert(i, i*2));
|
||||||
}
|
}
|
||||||
let mut observed = 0;
|
let mut observed = 0;
|
||||||
for m.each |k, v| {
|
for m.iter().advance |(k, v)| {
|
||||||
assert_eq!(*v, *k * 2);
|
assert_eq!(*v, *k * 2);
|
||||||
observed |= (1 << *k);
|
observed |= (1 << *k);
|
||||||
}
|
}
|
||||||
@ -885,6 +950,7 @@ mod test_set {
|
|||||||
use super::*;
|
use super::*;
|
||||||
use container::{Container, Map, Set};
|
use container::{Container, Map, Set};
|
||||||
use vec;
|
use vec;
|
||||||
|
use uint;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_disjoint() {
|
fn test_disjoint() {
|
||||||
@ -937,6 +1003,19 @@ mod test_set {
|
|||||||
assert!(b.is_superset(&a));
|
assert!(b.is_superset(&a));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_iterate() {
|
||||||
|
let mut a = HashSet::new();
|
||||||
|
for uint::range(0, 32) |i| {
|
||||||
|
assert!(a.insert(i));
|
||||||
|
}
|
||||||
|
let mut observed = 0;
|
||||||
|
for a.iter().advance |k| {
|
||||||
|
observed |= (1 << *k);
|
||||||
|
}
|
||||||
|
assert_eq!(observed, 0xFFFF_FFFF);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_intersection() {
|
fn test_intersection() {
|
||||||
let mut a = HashSet::new();
|
let mut a = HashSet::new();
|
||||||
|
@ -23,6 +23,7 @@ use hash::Hash;
|
|||||||
use cmp::Eq;
|
use cmp::Eq;
|
||||||
use old_iter::BaseIter;
|
use old_iter::BaseIter;
|
||||||
use vec::ImmutableVector;
|
use vec::ImmutableVector;
|
||||||
|
use iterator::IteratorUtil;
|
||||||
|
|
||||||
/// A generic trait for converting a value to a string
|
/// A generic trait for converting a value to a string
|
||||||
pub trait ToStr {
|
pub trait ToStr {
|
||||||
@ -56,7 +57,7 @@ impl<A:ToStr+Hash+Eq, B:ToStr+Hash+Eq> ToStr for HashMap<A, B> {
|
|||||||
#[inline]
|
#[inline]
|
||||||
fn to_str(&self) -> ~str {
|
fn to_str(&self) -> ~str {
|
||||||
let mut (acc, first) = (~"{", true);
|
let mut (acc, first) = (~"{", true);
|
||||||
for self.each |key, value| {
|
for self.iter().advance |(key, value)| {
|
||||||
if first {
|
if first {
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
@ -76,7 +77,7 @@ impl<A:ToStr+Hash+Eq> ToStr for HashSet<A> {
|
|||||||
#[inline]
|
#[inline]
|
||||||
fn to_str(&self) -> ~str {
|
fn to_str(&self) -> ~str {
|
||||||
let mut (acc, first) = (~"{", true);
|
let mut (acc, first) = (~"{", true);
|
||||||
for self.each |element| {
|
for self.iter().advance |element| {
|
||||||
if first {
|
if first {
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user