如何向Iterator添加新方法? [英] 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
,但你的vector提供了一个& 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
是一个supertrait时,我们将有权访问相关类型 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
.
此特征定义了唯一
方法,该方法仅在迭代项可以为以下时调用:
This trait defines the unique
method, which is only valid to call when then iterated item can be:
- Hashed
- 比较完全平等
- 克隆
此外,它要求实现 Iterator
的项目具有已知大小编译时间。这样做是为了通过唯一
迭代器适配器消耗迭代器。
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 {}
这篇关于如何向Iterator添加新方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!