迭代连续折叠结果的惯用和功能方法是什么?
What is the idiomatic and functional way to iterate over successive fold results?
我有一个序列(列表,迭代器)a0, a1, a2, ...
,我用一个函数f
来折叠。我想要一个能给我
的发电机
a0, f(a0, a1), f(f(a0, a1), a2), ...
这类似于 Mathematica 中的 FoldList
。有可用的 fold_list
功能吗?我没找到。
我想说最接近的抽象是 Iterator::scan
。它更强大一点,因为它有一个内部可变状态(即可以为生成的迭代器产生不同的值)并且可以提前中止。
您可以像这样使用它来构建迭代器扩展特征:
pub trait FoldListExt: Iterator {
fn fold_list<'a, St: 'a, F: 'a>(self, initial_state: St, f: F) -> Box<Iterator<Item = St> + 'a>
where
St: Clone,
F: FnMut(St, Self::Item) -> St,
Self: 'a;
}
impl<I: Iterator> FoldListExt for I {
fn fold_list<'a, St: 'a, F: 'a>(
self,
initial_state: St,
mut f: F,
) -> Box<Iterator<Item = St> + 'a>
where
St: Clone,
F: FnMut(St, Self::Item) -> St,
Self: 'a,
{
Box::new(self.scan(Some(initial_state), move |state, item| {
let old_state = state.take().unwrap();
*state = Some(f(old_state.clone(), item));
Some(old_state)
}))
}
}
pub fn main() {
println!(
"{:?}",
(0..16)
.into_iter()
.fold_list(0, |a, b| a + b)
.collect::<Vec<_>>()
);
}
我使用 Option<St>
作为内部可变状态以避免另一个 clone()
调用。
您可以改用这个:
Box::new(self.scan(initial_state, move |state, item| {
let old_state = state.clone();
*state = f(old_state.clone(), item);
Some(old_state)
}))
我有一个序列(列表,迭代器)a0, a1, a2, ...
,我用一个函数f
来折叠。我想要一个能给我
a0, f(a0, a1), f(f(a0, a1), a2), ...
这类似于 Mathematica 中的 FoldList
。有可用的 fold_list
功能吗?我没找到。
我想说最接近的抽象是 Iterator::scan
。它更强大一点,因为它有一个内部可变状态(即可以为生成的迭代器产生不同的值)并且可以提前中止。
您可以像这样使用它来构建迭代器扩展特征:
pub trait FoldListExt: Iterator {
fn fold_list<'a, St: 'a, F: 'a>(self, initial_state: St, f: F) -> Box<Iterator<Item = St> + 'a>
where
St: Clone,
F: FnMut(St, Self::Item) -> St,
Self: 'a;
}
impl<I: Iterator> FoldListExt for I {
fn fold_list<'a, St: 'a, F: 'a>(
self,
initial_state: St,
mut f: F,
) -> Box<Iterator<Item = St> + 'a>
where
St: Clone,
F: FnMut(St, Self::Item) -> St,
Self: 'a,
{
Box::new(self.scan(Some(initial_state), move |state, item| {
let old_state = state.take().unwrap();
*state = Some(f(old_state.clone(), item));
Some(old_state)
}))
}
}
pub fn main() {
println!(
"{:?}",
(0..16)
.into_iter()
.fold_list(0, |a, b| a + b)
.collect::<Vec<_>>()
);
}
我使用 Option<St>
作为内部可变状态以避免另一个 clone()
调用。
您可以改用这个:
Box::new(self.scan(initial_state, move |state, item| {
let old_state = state.clone();
*state = f(old_state.clone(), item);
Some(old_state)
}))