Skip to content

Commit

Permalink
map: Make Eq comparisons ordering-aware.
Browse files Browse the repository at this point in the history
This is a breaking change. Not sure if you really want to take this but
I think it's the right thing to do.

Fixes indexmap-rs#153
  • Loading branch information
emilio committed Sep 8, 2020
1 parent 008e543 commit 78bf6cd
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 9 deletions.
27 changes: 26 additions & 1 deletion src/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,23 @@ where
}
}

/// Performs an equality comparison without accounting for the ordering of
/// the keys.
///
/// This is effectively an equivalent to HashMap::eq.
pub fn unordered_eq<V2, S2>(&self, other: &IndexMap<K, V2, S2>) -> bool
where
V: PartialEq<V2>,
S2: BuildHasher,
{
if self.len() != other.len() {
return false;
}

self.iter()
.all(|(key, value)| other.get(key).map_or(false, |v| *value == *v))
}

/// Return references to the key-value pair stored for `key`,
/// if it is present, else `None`.
///
Expand Down Expand Up @@ -1244,7 +1261,8 @@ where
}

self.iter()
.all(|(key, value)| other.get(key).map_or(false, |v| *value == *v))
.zip(other.iter())
.all(|((k1, v1), (k2, v2))| k1 == k2 && v1 == v2)
}
}

Expand Down Expand Up @@ -1624,4 +1642,11 @@ mod tests {
assert!(values.contains(&4));
assert!(values.contains(&6));
}

#[test]
fn eq() {
let m1: IndexMap<_, _> = vec![(1, 1), (2, 2)].into_iter().collect();
let m2: IndexMap<_, _> = vec![(2, 2), (1, 1)].into_iter().collect();
assert_ne!(m1, m2);
}
}
22 changes: 15 additions & 7 deletions src/set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -820,7 +820,7 @@ where
S2: BuildHasher,
{
fn eq(&self, other: &IndexSet<T, S2>) -> bool {
self.len() == other.len() && self.is_subset(other)
self.len() == other.len() && self.iter().zip(other.iter()).all(|(v1, v2)| v1 == v2)
}
}

Expand Down Expand Up @@ -863,6 +863,14 @@ where
{
other.is_subset(self)
}

/// Performs an equality comparison without accounting for ordering.
pub fn unordered_eq<S2>(&self, other: &IndexSet<T, S2>) -> bool
where
S2: BuildHasher,
{
self.len() == other.len() && self.is_subset(other)
}
}

/// A lazy iterator producing elements in the difference of `IndexSet`s.
Expand Down Expand Up @@ -1580,9 +1588,9 @@ mod tests {
assert_eq!(&set_a & &set_b, empty);
assert_eq!(&set_b & &set_a, empty);
assert_eq!(&set_a | &set_b, set_c);
assert_eq!(&set_b | &set_a, set_c);
assert_ne!(&set_b | &set_a, set_c);
assert_eq!(&set_a ^ &set_b, set_c);
assert_eq!(&set_b ^ &set_a, set_c);
assert_ne!(&set_b ^ &set_a, set_c);
assert_eq!(&set_a - &set_b, set_a);
assert_eq!(&set_b - &set_a, set_b);

Expand All @@ -1596,11 +1604,11 @@ mod tests {
assert_eq!(&set_c - &set_a, set_b);

assert_eq!(&set_c & &set_d, set_b);
assert_eq!(&set_d & &set_c, set_b);
assert_eq!(&set_c | &set_d, &set_a | &set_d);
assert_eq!(&set_d | &set_c, &set_a | &set_d);
assert_ne!(&set_d & &set_c, set_b);
assert_ne!(&set_c | &set_d, &set_a | &set_d);
assert_ne!(&set_d | &set_c, &set_a | &set_d);
assert_eq!(&set_c ^ &set_d, &set_a | &(&set_d - &set_b));
assert_eq!(&set_d ^ &set_c, &set_a | &(&set_d - &set_b));
assert_ne!(&set_d ^ &set_c, &set_a | &(&set_d - &set_b));
assert_eq!(&set_c - &set_d, set_a);
assert_eq!(&set_d - &set_c, &set_d - &set_b);
}
Expand Down
2 changes: 1 addition & 1 deletion tests/quick.rs
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ quickcheck! {
let mut map2 = IndexMapFnv::default();
let mut reference2 = HashMap::new();
do_ops(&ops2, &mut map2, &mut reference2);
assert_eq!(map == map2, reference == reference2);
assert_eq!(map.unordered_eq(&map2), reference == reference2);
true
}

Expand Down

0 comments on commit 78bf6cd

Please sign in to comment.