Skip to content

Commit

Permalink
Add symmetrical_difference to sets/maps
Browse files Browse the repository at this point in the history
  • Loading branch information
AljoschaMeyer committed May 10, 2019
1 parent c0a8fc6 commit 01f2726
Show file tree
Hide file tree
Showing 4 changed files with 216 additions and 18 deletions.
89 changes: 82 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 difference between two maps by using a function
/// 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, 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 @@ -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 Down
28 changes: 26 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 Down
89 changes: 82 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 difference between two maps by using a function
/// 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 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 Down
28 changes: 26 additions & 2 deletions src/ord/set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -587,7 +587,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 @@ -604,7 +607,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::ordset::OrdSet;
/// # fn main() {
/// let set1 = ordset!{1, 2};
/// let set2 = ordset!{2, 3};
/// let expected = ordset!{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 Down

0 comments on commit 01f2726

Please sign in to comment.