gpt4 book ai didi

rust - 用 "mean"方法扩展 Iterator

转载 作者:行者123 更新时间:2023-11-29 08:22:08 26 4
gpt4 key购买 nike

我正在尝试为 Iterator 实现一个 mean 方法,就像用 sum 完成的那样。但是,sumIterator 方法,所以我决定为任何实现 Iterator 的类型实现 trait:

pub trait Mean<A = Self>: Sized {
fn mean<I: Iterator<Item = A>>(iter: I) -> f64;
}

impl Mean for u64 {
fn mean<I: Iterator<Item = u64>>(iter: I) -> f64 {
//use zip to start enumeration from 1, not 0
iter.zip((1..))
.fold(0., |s, (e, i)| (e as f64 + s * (i - 1) as f64) / i as f64)
}
}

impl<'a> Mean<&'a u64> for u64 {
fn mean<I: Iterator<Item = &'a u64>>(iter: I) -> f64 {
iter.zip((1..))
.fold(0., |s, (&e, i)| (e as f64 + s * (i - 1) as f64) / i as f64)
}
}

trait MeanIterator: Iterator {
fn mean(self) -> f64;
}

impl<T: Iterator> MeanIterator for T {
fn mean(self) -> f64 {
Mean::mean(self)
}
}

fn main() {
assert_eq!([1, 2, 3, 4, 5].iter().mean(), 3.);
}

Playground

错误:

error[E0282]: type annotations needed
--> src/main.rs:26:9
|
26 | Mean::mean(self)
| ^^^^^^^^^^ cannot infer type for `Self`

有没有办法修复代码,或者在 Rust 中是不可能的?

最佳答案

like it is done with sum

让我们回顾一下sum 的工作原理:

pub fn sum<S>(self) -> S
where
S: Sum<Self::Item>,

sum 在任何迭代器上实现,只要结果类型 S 为迭代值实现 Sum调用者 可以选择结果类型。 Sum 定义为:

pub trait Sum<A = Self> {
pub fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = A>;
}

Sum::sum 获取 A 的迭代器并生成一个实现它的类型的值。

我们可以复制粘贴结构,将 Sum 更改为 Mean 并放置简单的实现:

trait MeanExt: Iterator {
fn mean<M>(self) -> M
where
M: Mean<Self::Item>,
Self: Sized,
{
M::mean(self)
}
}

impl<I: Iterator> MeanExt for I {}

trait Mean<A = Self> {
fn mean<I>(iter: I) -> Self
where
I: Iterator<Item = A>;
}

impl Mean for f64 {
fn mean<I>(iter: I) -> Self
where
I: Iterator<Item = f64>,
{
let mut sum = 0.0;
let mut count: usize = 0;

for v in iter {
sum += v;
count += 1;
}

if count > 0 {
sum / (count as f64)
} else {
0.0
}
}
}

impl<'a> Mean<&'a f64> for f64 {
fn mean<I>(iter: I) -> Self
where
I: Iterator<Item = &'a f64>,
{
iter.copied().mean()
}
}

fn main() {
let mean: f64 = [1.0, 2.0, 3.0].iter().mean();
println!("{:?}", mean);
let mean: f64 = std::array::IntoIter::new([-1.0, 2.0, 1.0]).mean();
println!("{:?}", mean);
}

关于rust - 用 "mean"方法扩展 Iterator,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43921436/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com