如何向迭代器添加新方法? [英] How can I add new methods to Iterator?
问题描述
我想在迭代器上定义一个 .unique()
方法,使我能够在没有重复的情况下进行迭代.
I want to define a .unique()
method on iterators that enables me to iterate without duplicates.
use std::collections::HashSet;
struct UniqueState<'a> {
seen: HashSet<String>,
underlying: &'a mut Iterator<Item = String>,
}
trait Unique {
fn unique(&mut self) -> UniqueState;
}
impl Unique for Iterator<Item = String> {
fn unique(&mut self) -> UniqueState {
UniqueState {
seen: HashSet::new(),
underlying: self,
}
}
}
impl<'a> Iterator for UniqueState<'a> {
type Item = String;
fn next(&mut self) -> Option<String> {
while let Some(x) = self.underlying.next() {
if !self.seen.contains(&x) {
self.seen.insert(x.clone());
return Some(x);
}
}
None
}
}
这就编译了.但是,当我尝试在同一个文件中使用时:
This compiles. However, when I try to use in the same file:
fn main() {
let foo = vec!["a", "b", "a", "cc", "cc", "d"];
for s in foo.iter().unique() {
println!("{}", s);
}
}
我收到以下错误:
error[E0599]: no method named `unique` found for type `std::slice::Iter<'_, &str>` in the current scope
--> src/main.rs:37:25
|
37 | for s in foo.iter().unique() {
| ^^^^^^
|
= help: items from traits can only be used if the trait is implemented and in scope
= note: the following trait defines an item `unique`, perhaps you need to implement it:
candidate #1: `Unique`
我做错了什么?我将如何扩展这种任意的可散列类型?
What am I doing wrong? How would I extend this arbitrary hashable types?
推荐答案
在你的特殊情况下,这是因为你已经为 String
的迭代器实现了你的特征,但是你的向量提供了一个迭代器&str
.这是一个更通用的版本:
In your particular case, it's because you have implemented your trait for an iterator of String
, but your vector is providing an iterator of &str
. Here's a more generic version:
use std::collections::HashSet;
use std::hash::Hash;
struct Unique<I>
where
I: Iterator,
{
seen: HashSet<I::Item>,
underlying: I,
}
impl<I> Iterator for Unique<I>
where
I: Iterator,
I::Item: Hash + Eq + Clone,
{
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
while let Some(x) = self.underlying.next() {
if !self.seen.contains(&x) {
self.seen.insert(x.clone());
return Some(x);
}
}
None
}
}
trait UniqueExt: Iterator {
fn unique(self) -> Unique<Self>
where
Self::Item: Hash + Eq + Clone,
Self: Sized,
{
Unique {
seen: HashSet::new(),
underlying: self,
}
}
}
impl<I: Iterator> UniqueExt for I {}
fn main() {
let foo = vec!["a", "b", "a", "cc", "cc", "d"];
for s in foo.iter().unique() {
println!("{}", s);
}
}
从广义上讲,我们创建了一个名为 UniqueExt
的新扩展特征,它具有 Iterator
作为超特征.当 Iterator
是超特征时,我们将可以访问 关联类型 Iterator::Item
.
Broadly, we create a new extension trait called UniqueExt
which has Iterator
as a supertrait. When Iterator
is a supertrait, we will have access to the associated type Iterator::Item
.
这个 trait 定义了 unique
方法,只有当迭代项可以是:
This trait defines the unique
method, which is only valid to call when then iterated item can be:
- 散列
- 比较完全平等
- 克隆
此外,它要求实现 Iterator
的项目在编译时具有已知的大小.这样做是为了使迭代器可以被 Unique
迭代器适配器使用.
Additionally, it requires that the item implementing Iterator
have a known size at compile time. This is done so that the iterator can be consumed by the Unique
iterator adapter.
另一个重要的部分是一揽子实现特征的任何类型也实现了Iterator
:
The other important part is the blanket implementation of the trait for any type that also implements Iterator
:
impl<I: Iterator> UniqueExt for I {}
这篇关于如何向迭代器添加新方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!