Skip to content

Commit

Permalink
Merge pull request #89 from AljoschaMeyer/master
Browse files Browse the repository at this point in the history
Add relative_complement and symmetric_difference
  • Loading branch information
bodil authored May 10, 2019
2 parents c0a8fc6 + f519c66 commit d2befa1
Show file tree
Hide file tree
Showing 4 changed files with 318 additions and 18 deletions.
115 changes: 108 additions & 7 deletions src/hash/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -978,9 +978,12 @@ where
.fold(Self::default(), |a, b| a.union_with_key(b, &f))
}

/// Construct the difference between two maps by discarding keys
/// Construct the symmetric difference between two maps by discarding keys
/// which occur in both maps.
///
/// This is an alias for the
/// [`symmetric_difference`][symmetric_difference] method.
///
/// Time: O(n log n)
///
/// # Examples
Expand All @@ -998,26 +1001,69 @@ where
#[inline]
#[must_use]
pub fn difference(self, other: Self) -> Self {
self.difference_with_key(other, |_, _, _| None)
self.symmetric_difference(other)
}

/// Construct the symmetric difference between two maps by discarding keys
/// which occur in both maps.
///
/// Time: O(n log n)
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate im;
/// # use im::hashmap::HashMap;
/// # fn main() {
/// let map1 = hashmap!{1 => 1, 3 => 4};
/// let map2 = hashmap!{2 => 2, 3 => 5};
/// let expected = hashmap!{1 => 1, 2 => 2};
/// assert_eq!(expected, map1.symmetric_difference(map2));
/// # }
/// ```
#[inline]
#[must_use]
pub fn symmetric_difference(self, other: Self) -> Self {
self.symmetric_difference_with_key(other, |_, _, _| None)
}

/// Construct the symmetric difference between two maps by using a function
/// to decide what to do if a key occurs in both.
///
/// This is an alias for the
/// [`symmetric_difference_with`][symmetric_difference_with] method.
///
/// Time: O(n log n)
#[inline]
#[must_use]
pub fn difference_with<F>(self, other: Self, f: F) -> Self
where
F: FnMut(V, V) -> Option<V>,
{
self.symmetric_difference_with(other, f)
}

/// Construct the difference between two maps by using a function
/// Construct the symmetric difference between two maps by using a function
/// to decide what to do if a key occurs in both.
///
/// Time: O(n log n)
#[inline]
#[must_use]
pub fn difference_with<F>(self, other: Self, mut f: F) -> Self
pub fn symmetric_difference_with<F>(self, other: Self, mut f: F) -> Self
where
F: FnMut(V, V) -> Option<V>,
{
self.difference_with_key(other, |_, a, b| f(a, b))
self.symmetric_difference_with_key(other, |_, a, b| f(a, b))
}

/// Construct the difference between two maps by using a function
/// Construct the symmetric difference between two maps by using a function
/// to decide what to do if a key occurs in both. The function
/// receives the key as well as both values.
///
/// This is an alias for the
/// [`symmetric_difference_with`_key][symmetric_difference_with_key]
/// method.
///
/// Time: O(n log n)
///
/// # Examples
Expand All @@ -1036,7 +1082,36 @@ where
/// # }
/// ```
#[must_use]
pub fn difference_with_key<F>(mut self, other: Self, mut f: F) -> Self
pub fn difference_with_key<F>(self, other: Self, f: F) -> Self
where
F: FnMut(&K, V, V) -> Option<V>,
{
self.symmetric_difference_with_key(other, f)
}

/// Construct the symmetric difference between two maps by using a function
/// to decide what to do if a key occurs in both. The function
/// receives the key as well as both values.
///
/// Time: O(n log n)
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate im;
/// # use im::hashmap::HashMap;
/// # fn main() {
/// let map1 = hashmap!{1 => 1, 3 => 4};
/// let map2 = hashmap!{2 => 2, 3 => 5};
/// let expected = hashmap!{1 => 1, 2 => 2, 3 => 9};
/// assert_eq!(expected, map1.symmetric_difference_with_key(
/// map2,
/// |key, left, right| Some(left + right)
/// ));
/// # }
/// ```
#[must_use]
pub fn symmetric_difference_with_key<F>(mut self, other: Self, mut f: F) -> Self
where
F: FnMut(&K, V, V) -> Option<V>,
{
Expand All @@ -1056,6 +1131,32 @@ where
out.union(self)
}

/// Construct the relative complement between two maps by discarding keys
/// which occur in `other`.
///
/// Time: O(m log n) where m is the size of the other map
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate im;
/// # use im::ordmap::OrdMap;
/// # fn main() {
/// let map1 = ordmap!{1 => 1, 3 => 4};
/// let map2 = ordmap!{2 => 2, 3 => 5};
/// let expected = ordmap!{1 => 1};
/// assert_eq!(expected, map1.relative_complement(map2));
/// # }
/// ```
#[inline]
#[must_use]
pub fn relative_complement(mut self, other: Self) -> Self {
for (key, _) in other {
let _ = self.remove(&key);
}
self
}

/// Construct the intersection of two maps, keeping the values
/// from the current map.
///
Expand Down
53 changes: 51 additions & 2 deletions src/hash/set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -487,7 +487,10 @@ where
i.into_iter().fold(Self::default(), Self::union)
}

/// Construct the difference between two sets.
/// Construct the symmetric difference between two sets.
///
/// This is an alias for the
/// [`symmetric_difference`][symmetric_difference] method.
///
/// Time: O(n log n)
///
Expand All @@ -504,7 +507,28 @@ where
/// # }
/// ```
#[must_use]
pub fn difference(mut self, other: Self) -> Self {
pub fn difference(self, other: Self) -> Self {
self.symmetric_difference(other)
}

/// Construct the symmetric difference between two sets.
///
/// Time: O(n log n)
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate im;
/// # use im::hashset::HashSet;
/// # fn main() {
/// let set1 = hashset!{1, 2};
/// let set2 = hashset!{2, 3};
/// let expected = hashset!{1, 3};
/// assert_eq!(expected, set1.symmetric_difference(set2));
/// # }
/// ```
#[must_use]
pub fn symmetric_difference(mut self, other: Self) -> Self {
for value in other {
if self.remove(&value).is_none() {
self.insert(value);
Expand All @@ -513,6 +537,31 @@ where
self
}

/// Construct the relative complement between two sets, that is the set
/// of values in `self` that do not occur in `other`.
///
/// Time: O(m log n) where m is the size of the other set
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate im;
/// # use im::ordset::OrdSet;
/// # fn main() {
/// let set1 = ordset!{1, 2};
/// let set2 = ordset!{2, 3};
/// let expected = ordset!{1};
/// assert_eq!(expected, set1.relative_complement(set2));
/// # }
/// ```
#[must_use]
pub fn relative_complement(mut self, other: Self) -> Self {
for value in other {
let _ = self.remove(&value);
}
self
}

/// Construct the intersection of two sets.
///
/// Time: O(n log n)
Expand Down
115 changes: 108 additions & 7 deletions src/ord/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -942,9 +942,12 @@ where
.fold(Self::default(), |a, b| a.union_with_key(b, &f))
}

/// Construct the difference between two maps by discarding keys
/// Construct the symmetric difference between two maps by discarding keys
/// which occur in both maps.
///
/// This is an alias for the
/// [`symmetric_difference`][symmetric_difference] method.
///
/// Time: O(n log n)
///
/// # Examples
Expand All @@ -962,26 +965,69 @@ where
#[inline]
#[must_use]
pub fn difference(self, other: Self) -> Self {
self.difference_with_key(other, |_, _, _| None)
self.symmetric_difference(other)
}

/// Construct the symmetric difference between two maps by discarding keys
/// which occur in both maps.
///
/// Time: O(n log n)
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate im;
/// # use im::ordmap::OrdMap;
/// # fn main() {
/// let map1 = ordmap!{1 => 1, 3 => 4};
/// let map2 = ordmap!{2 => 2, 3 => 5};
/// let expected = ordmap!{1 => 1, 2 => 2};
/// assert_eq!(expected, map1.symmetric_difference(map2));
/// # }
/// ```
#[inline]
#[must_use]
pub fn symmetric_difference(self, other: Self) -> Self {
self.symmetric_difference_with_key(other, |_, _, _| None)
}

/// Construct the difference between two maps by using a function
/// Construct the symmetric difference between two maps by using a function
/// to decide what to do if a key occurs in both.
///
/// This is an alias for the
/// [`symmetric_difference_with`][symmetric_difference_with] method.
///
/// Time: O(n log n)
#[inline]
#[must_use]
pub fn difference_with<F>(self, other: Self, mut f: F) -> Self
pub fn difference_with<F>(self, other: Self, f: F) -> Self
where
F: FnMut(V, V) -> Option<V>,
{
self.difference_with_key(other, |_, a, b| f(a, b))
self.symmetric_difference_with(other, f)
}

/// Construct the difference between two maps by using a function
/// Construct the symmetric difference between two maps by using a function
/// to decide what to do if a key occurs in both.
///
/// Time: O(n log n)
#[inline]
#[must_use]
pub fn symmetric_difference_with<F>(self, other: Self, mut f: F) -> Self
where
F: FnMut(V, V) -> Option<V>,
{
self.symmetric_difference_with_key(other, |_, a, b| f(a, b))
}

/// Construct the symmetric difference between two maps by using a function
/// to decide what to do if a key occurs in both. The function
/// receives the key as well as both values.
///
/// This is an alias for the
/// [`symmetric_difference_with_key`][symmetric_difference_with_key]
/// method.
///
/// Time: O(n log n)
///
/// # Examples
Expand All @@ -1000,7 +1046,36 @@ where
/// # }
/// ```
#[must_use]
pub fn difference_with_key<F>(mut self, other: Self, mut f: F) -> Self
pub fn difference_with_key<F>(self, other: Self, f: F) -> Self
where
F: FnMut(&K, V, V) -> Option<V>,
{
self.symmetric_difference_with_key(other, f)
}

/// Construct the symmetric difference between two maps by using a function
/// to decide what to do if a key occurs in both. The function
/// receives the key as well as both values.
///
/// Time: O(n log n)
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate im;
/// # use im::ordmap::OrdMap;
/// # fn main() {
/// let map1 = ordmap!{1 => 1, 3 => 4};
/// let map2 = ordmap!{2 => 2, 3 => 5};
/// let expected = ordmap!{1 => 1, 2 => 2, 3 => 9};
/// assert_eq!(expected, map1.symmetric_difference_with_key(
/// map2,
/// |key, left, right| Some(left + right)
/// ));
/// # }
/// ```
#[must_use]
pub fn symmetric_difference_with_key<F>(mut self, other: Self, mut f: F) -> Self
where
F: FnMut(&K, V, V) -> Option<V>,
{
Expand All @@ -1020,6 +1095,32 @@ where
out.union(self)
}

/// Construct the relative complement between two maps by discarding keys
/// which occur in `other`.
///
/// Time: O(m log n) where m is the size of the other map
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate im;
/// # use im::ordmap::OrdMap;
/// # fn main() {
/// let map1 = ordmap!{1 => 1, 3 => 4};
/// let map2 = ordmap!{2 => 2, 3 => 5};
/// let expected = ordmap!{1 => 1};
/// assert_eq!(expected, map1.relative_complement(map2));
/// # }
/// ```
#[inline]
#[must_use]
pub fn relative_complement(mut self, other: Self) -> Self {
for (key, _) in other {
let _ = self.remove(&key);
}
self
}

/// Construct the intersection of two maps, keeping the values
/// from the current map.
///
Expand Down
Loading

0 comments on commit d2befa1

Please sign in to comment.