首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在迭代器扩展中处理生命类型

在迭代器扩展中处理生命类型
EN

Stack Overflow用户
提问于 2022-04-14 00:08:32
回答 1查看 36关注 0票数 0

我试图用group_by_count方法扩展Iterator:

代码语言:javascript
复制
use itertools::Itertools;

trait ExtIterator<T>
where
    T: Sized,
{
    fn group_by_count(self) -> Box<dyn Iterator<Item = (T, usize)>>
    where
        T: Sized;
}

impl<T: 'static, I: 'static> ExtIterator<T> for I
where
    I: Iterator<Item = T> + Sized,
    T: Clone + Eq + PartialEq + Sized,
{
    fn group_by_count(self) -> Box<dyn Iterator<Item = (T, usize)>>
    where
        Self: Sized,
    {
        Box::new(
            self.group_by(|i| i.clone())
                .into_iter()
                .map(|(key, group)| (key, group.count())),
        )
    }
}

我得到了:

代码语言:javascript
复制
error[E0515]: cannot return value referencing temporary value
  --> src/ext/iterator.rs:21:9
   |
21 | /         Box::new(
22 | |             self.group_by(|i| i.clone())
   | |             ---------------------------- temporary value created here
23 | |                 .into_iter()
24 | |                 .map(|(key, group)| (key, group.count())),
25 | |         )
   | |_________^ returns a value referencing data owned by the current function
   |
   = help: use `.collect()` to allocate the iterator

在这里调用collect是不对的,而clippy建议如果我这样做,collect应该被删除。但我想不出如何避免创造一个暂时的价值。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-04-14 01:17:17

如果没有自定义迭代器适配器,就不能这样做。

但是很容易创建一个新的GroupByCount迭代器,然后根据对into_iter() on GroupBy的多次调用更改底层迭代器的事实,实现它的next()方法:

代码语言:javascript
复制
pub struct GroupByCount<I: Iterator> {
    // This `fn(&K) -> K` could be `Box<dyn FnMut(&K) -> K`, but
    // this adds one usize to the struct's size, and the function
    // captures nothing.
    inner: itertools::structs::GroupBy<I::Item, I, fn(&I::Item) -> I::Item>,
}

impl<I> Iterator for GroupByCount<I>
where
    I: Iterator,
    I::Item: PartialEq,
{
    type Item = (I::Item, usize);

    fn next(&mut self) -> Option<Self::Item> {
        self.inner
            .into_iter()
            .next()
            .map(|(key, group)| (key, group.count()))
    }
}

pub trait IteratorExt: Iterator {
    fn group_by_count(self) -> GroupByCount<Self>
    where
        Self: Sized;
}

impl<I> IteratorExt for I
where
    I: Iterator,
    I::Item: Clone + PartialEq,
{
    fn group_by_count(self) -> GroupByCount<Self>
    where
        Self: Sized,
    {
        GroupByCount {
            inner: self.group_by(|i| i.clone()),
        }
    }
}

游乐场

我所做的其他改进:

  • 删除多余的Sized边界。
  • 删除现在冗余的'static边界。
  • 删除Eq绑定,因为这是不必要的。
  • 去掉类型参数T,然后显式地使用I::Item
  • ExtIterator重命名为IteratorExt,与RFC 445,扩展特性公约相同。
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71865054

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档