From 99eb4ddddd68e9ffa86eb8df264934925e27d737 Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Tue, 29 Jan 2013 19:30:26 -0500 Subject: [PATCH] add difference and symmetric_difference to Set --- src/libcore/container.rs | 6 ++++ src/libcore/hashmap.rs | 65 ++++++++++++++++++++++++++++++++++++++++ src/libstd/treemap.rs | 34 ++++++++++----------- 3 files changed, 88 insertions(+), 17 deletions(-) diff --git a/src/libcore/container.rs b/src/libcore/container.rs index 3c9ee50855e2..15685ec67225 100644 --- a/src/libcore/container.rs +++ b/src/libcore/container.rs @@ -75,4 +75,10 @@ pub trait Set: Mutable { /// Return true if the set is a superset of another pure fn is_superset(&self, other: &self) -> bool; + + /// Visit the values representing the difference + pure fn difference(&self, other: &self, f: fn(&T) -> bool); + + /// Visit the values representing the symmetric difference + pure fn symmetric_difference(&self, other: &self, f: fn(&T) -> bool); } diff --git a/src/libcore/hashmap.rs b/src/libcore/hashmap.rs index cf99c0e46b97..5711c88e8907 100644 --- a/src/libcore/hashmap.rs +++ b/src/libcore/hashmap.rs @@ -469,6 +469,22 @@ pub mod linear { pure fn is_superset(&self, other: &LinearSet) -> bool { other.is_subset(self) } + + /// Visit the values representing the difference + pure fn difference(&self, other: &LinearSet, f: fn(&T) -> bool) { + for self.each |v| { + if !other.contains(v) { + if !f(v) { return; } + } + } + } + + /// Visit the values representing the symmetric difference + pure fn symmetric_difference(&self, other: &LinearSet, + f: fn(&T) -> bool) { + self.difference(other, f); + other.difference(self, f); + } } pub impl LinearSet { @@ -681,4 +697,53 @@ mod test_set { assert !b.is_subset(&a); assert b.is_superset(&a); } + + #[test] + fn test_difference() { + let mut a = linear::LinearSet::new(); + let mut b = linear::LinearSet::new(); + + assert a.insert(1); + assert a.insert(3); + assert a.insert(5); + assert a.insert(9); + assert a.insert(11); + + assert b.insert(3); + assert b.insert(9); + + let mut i = 0; + let expected = [1, 5, 11]; + for a.difference(&b) |x| { + assert vec::contains(expected, x); + i += 1 + } + assert i == expected.len(); + } + + #[test] + fn test_symmetric_difference() { + let mut a = linear::LinearSet::new(); + let mut b = linear::LinearSet::new(); + + assert a.insert(1); + assert a.insert(3); + assert a.insert(5); + assert a.insert(9); + assert a.insert(11); + + assert b.insert(-2); + assert b.insert(3); + assert b.insert(9); + assert b.insert(14); + assert b.insert(22); + + let mut i = 0; + let expected = [-2, 1, 5, 11, 14, 22]; + for a.symmetric_difference(&b) |x| { + assert vec::contains(expected, x); + i += 1 + } + assert i == expected.len(); + } } diff --git a/src/libstd/treemap.rs b/src/libstd/treemap.rs index b1c22f86c96a..235db2635429 100644 --- a/src/libstd/treemap.rs +++ b/src/libstd/treemap.rs @@ -29,10 +29,10 @@ use core::prelude::*; // range search - O(log n) retrieval of an iterator from some key // (possibly) implement the overloads Python does for sets: -// * union: | // * intersection: & // * difference: - // * symmetric difference: ^ +// * union: | // These would be convenient since the methods work like `each` pub struct TreeMap { @@ -355,22 +355,6 @@ impl TreeSet: Set { } true } -} - -impl TreeSet { - /// Create an empty TreeSet - static pure fn new() -> TreeSet { TreeSet{map: TreeMap::new()} } - - /// Visit all values in reverse order - pure fn each_reverse(&self, f: fn(&T) -> bool) { - self.map.each_key_reverse(f) - } - - /// Get a lazy iterator over the values in the set. - /// Requires that it be frozen (immutable). - pure fn iter(&self) -> TreeSetIterator/&self { - TreeSetIterator{iter: self.map.iter()} - } /// Visit the values (in-order) representing the difference pure fn difference(&self, other: &TreeSet, f: fn(&T) -> bool) { @@ -448,6 +432,22 @@ impl TreeSet { } } } +} + +impl TreeSet { + /// Create an empty TreeSet + static pure fn new() -> TreeSet { TreeSet{map: TreeMap::new()} } + + /// Visit all values in reverse order + pure fn each_reverse(&self, f: fn(&T) -> bool) { + self.map.each_key_reverse(f) + } + + /// Get a lazy iterator over the values in the set. + /// Requires that it be frozen (immutable). + pure fn iter(&self) -> TreeSetIterator/&self { + TreeSetIterator{iter: self.map.iter()} + } /// Visit the values (in-order) representing the intersection pure fn intersection(&self, other: &TreeSet, f: fn(&T) -> bool) {