Reputation: 10530
What's the best way to compare 2 vectors or strings element by element in Rust, while being able to do processing on each pair of elements? For example if you wanted to keep count of the number of differing elements. This is what I'm using:
let mut diff_count: i32 = 0i32;
for (x, y) in a.chars().zip(b.chars()) {
if x != y {
diff_count += 1i32;
}
}
Is that the correct way or is there something more canonical?
Upvotes: 26
Views: 33108
Reputation: 431669
To get the count of matching elements, I'd probably use filter
and count
.
fn main() {
let a = "Hello";
let b = "World";
let matching = a.chars().zip(b.chars()).filter(|&(a, b)| a == b).count();
println!("{}", matching);
let a = [1, 2, 3, 4, 5];
let b = [1, 1, 3, 3, 5];
let matching = a.iter().zip(&b).filter(|&(a, b)| a == b).count();
println!("{}", matching);
}
Iterator::zip
takes two iterators and produces another iterator of the tuple of each iterator's values.Iterator::filter
takes a reference to the iterator's value and discards any value where the predicate closure returns false
. This performs the comparison.Iterator::count
counts the number of elements in the iterator.Note that Iterator::zip
stops iterating when one iterator is exhausted. If you need different behavior, you may also be interested in
Itertools::zip_longest
or Itertools::zip_eq
.
Upvotes: 37
Reputation: 5553
If you wanted to use @Shepmaster's answer as the basis of an assertion to be used in a unit test, try this:
fn do_vecs_match<T: PartialEq>(a: &Vec<T>, b: &Vec<T>) -> bool {
let matching = a.iter().zip(b.iter()).filter(|&(a, b)| a == b).count();
matching == a.len() && matching == b.len()
}
Of course, be careful when using this on floats! Those pesky NaNs won't compare, and you might want to use a tolerance for comparing the other values. And you might want to make it fancy by telling the index of the first nonmatching value.
Upvotes: 11