Skip to content

Instantly share code, notes, and snippets.

@jupp0r
Last active September 7, 2016 08:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jupp0r/4ab19e3e03f291d5d9fff1ee2050a330 to your computer and use it in GitHub Desktop.
Save jupp0r/4ab19e3e03f291d5d9fff1ee2050a330 to your computer and use it in GitHub Desktop.
Unique Iterator in Rust
use std::collections::HashSet;
use std::option::Option;
use std::hash::{SipHasher, Hash, Hasher};
struct UniqueIterator<I> {
iter: I,
seen_items: HashSet<u64>,
}
fn hash_item<T>(item: &T) -> u64
where T: Hash
{
let mut hasher = SipHasher::new();
item.hash(&mut hasher);
hasher.finish()
}
impl<I> Iterator for UniqueIterator<I>
where I: Iterator,
I::Item: Hash + Sized
{
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
let seen_items = &mut self.seen_items;
match self.iter
.find(|x: &Self::Item| -> bool { !seen_items.contains(&hash_item(&x)) }) {
None => None,
Some(item) => {
seen_items.insert(hash_item(&item));
Some(item)
}
}
}
}
trait UniqueIteratorAdapter: Iterator {
fn unique(self) -> UniqueIterator<Self>
where Self: Sized,
Self::Item: Hash + Sized
{
UniqueIterator {
iter: self,
seen_items: HashSet::new(),
}
}
}
impl<I> UniqueIteratorAdapter for I where I: Iterator {}
fn main() {
let data = vec![1, 12, 15, 1, 12, 3, 5].into_iter().unique().collect::<Vec<_>>();
println!("{:?}", data);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment