如何向Iterator添加新方法? [英] How can I add new methods to Iterator?

查看:96
本文介绍了如何向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:


  1. Hashed

  2. 比较完全平等

  3. 克隆

此外,它要求实现 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆