Reputation: 1978
Let's say I have a vector of vectors vec_of_vecs = vec![vec![1,2],vec![1,3],vec![2,2],vec![2,3]]
. What would be the idiomatic way of filtering out vec![2,2]
.
My attempt was this:
fn filter_out_duplicates(vec_of_vecs: Vec<Vec<u8>>) -> Vec<Vec<u8>> {
vec_of_vecs
.into_iter()
.filter(all_unique)
.collect()
}
pub fn all_unique<T>(iterable: T) -> bool
where
T: IntoIterator,
T::Item: Eq + Hash,
{
let mut unique = HashSet::new();
iterable.into_iter().all(|x| unique.insert(x))
}
But this gives me an error message I'm having a hard time decoding the error
the method `collect` exists for struct `std::iter::Filter<std::vec::IntoIter<std::vec::Vec<u8>>, fn(&std::vec::Vec<u8>) -> bool {all_unique::<&std::vec::Vec<u8>>}>`, but its trait bounds were not satisfied
the following trait bounds were not satisfied:
`<fn(&std::vec::Vec<u8>) -> bool {all_unique::<&std::vec::Vec<u8>>} as std::ops::FnOnce<(&std::vec::Vec<u8>,)>>::Output = bool`
which is required by `std::iter::Filter<std::vec::IntoIter<std::vec::Vec<u8>>, fn(&std::vec::Vec<u8>) -> bool {all_unique::<&std::vec::Vec<u8>>}>: std::iter::Iterator`
`fn(&std::vec::Vec<u8>) -> bool {all_unique::<&std::vec::Vec<u8>>}: std::ops::FnMut<(&std::vec::Vec<u8>,)>`
which is required by `std::iter::Filter<std::vec::IntoIter<std::vec::Vec<u8>>, fn(&std::vec::Vec<u8>) -> bool {all_unique::<&std::vec::Vec<u8>>}>: std::iter::Iterator`
`std::iter::Filter<std::vec::IntoIter<std::vec::Vec<u8>>, fn(&std::vec::Vec<u8>) -> bool {all_unique::<&std::vec::Vec<u8>>}>: std::iter::Iterator`
which is required by `&mut std::iter::Filter<std::vec::IntoIter<std::vec::Vec<u8>>, fn(&std::vec::Vec<u8>) -> bool {all_unique::<&std::vec::Vec<u8>>}>: std::iter::Iterator`rustcE0599
filter.rs(15, 1): doesn't satisfy `_: std::iter::Iterator`
I believe what it's saying is that the iterator gets consumed in all_unique
but from what I've read online, it doesn't seem like there's a great way to generalize my all_unique
function to only consume references.
I could rewrite this using clone but I think there's a more idiomatic way to do it.
Upvotes: 1
Views: 201
Reputation: 410
Update: checkout this answer for another question for why filter(all_unique)
doesn't work.
all_unique
doesn't need to consume a Vec, IntoIterator
should be also implemented for the reference.
Here's a working example, the only real difference is instead of filter(all_unique)
, I used filter(|v| all_unique(v))
use std::hash::Hash;
use std::collections::HashSet;
fn filter_out_duplicates(vec_of_vecs: Vec<Vec<u8>>) -> Vec<Vec<u8>> {
vec_of_vecs
.into_iter()
.filter(|v| all_unique(v))
.collect()
}
pub fn all_unique<T>(iterable: T) -> bool
where
T: IntoIterator,
T::Item: Eq + Hash,
{
let mut unique = HashSet::new();
iterable.into_iter().all(|x| unique.insert(x))
}
Upvotes: 2