In your second example, a.into_iter()
consumes the values in a
, and then collects them as owned values in the returned Vec.
In your first example, the values are not consumed. Instead, they're cloned (so you need the Clone trait).
You can get the same requirements on the first version by consuming a
in the same way:
// Get rid of Clone requirement
fn array_diff<T: PartialEq>(a: Vec<T>, b: Vec<T>) -> Vec<T> {
let mut res: Vec<T> = Vec::new();
for av in a { // <--- remove the `.iter()`. Now `av` is owned.
let mut found = false;
for bv in b.iter() { // <-- Can't consume b; it's searched multiple times
if av == *bv { // <-- No `*` on the av because it's owned.
found = true;
break;
}
}
if !found {
res.push(av); // <-- push the owned value, not a clone
}
}
return res;
}
for
loops call .into_iter()
implicitly (that's how a for
loop works).
iter()
creates a immutable, borrowing Iterator by convention.
Note that both of these functions take ownership of their parameters, which is a little strange IMO for a diffing function. Another way to build this is to apply the Clone requirement to the second example and pass references rather than owned values (this is my preferred solution because it's probably the simplest to use):
fn array_diff<T: PartialEq + Clone>(a: &[T], b: &[T]) -> Vec<T> {
a.iter()
.filter(|x| !b.contains(x))
.cloned()
.collect()
}
(For the switch from Vec
to []
, see Cerberus's comments below.)
Or the results can be references to the first slice (iter()
rather than iter_into()
) to avoid any copying, but now you need to worry about the lifetime of a
, which can make usage more complicated:
fn array_diff<'a, T: PartialEq>(a: &'a [T], b: &[T]) -> Vec<&'a T> {
a.iter().filter(|x| !b.contains(x)).collect()
}