为什么双反转迭代器的行为好像从未被逆转过?

mrb*_*007 8 rust

我有一个包含数字的输入向量.在输出向量中,我需要以从右到左的顺序获得一系列部分乘积.输出的最后一个元素必须等于输入中的最后一个元素; 输出的倒数第二个元素必须是输入的最后一个和倒数第二个元素的乘积; 等等.例如,如果输入向量是

let input = vec![2, 3, 4];
Run Code Online (Sandbox Code Playgroud)

然后我需要输出[24, 12, 4].

我的实现在输入上使用迭代器,反转它,maps,再次反转和collects:

fn main() {
    let input = vec![2, 3, 4];
    let mut prod = 1;
    let p: Vec<usize> = input
        .iter()
        .rev()
        .map(|v| {
            prod *= v;
            prod
        }).rev()
        .collect();
    println!("{:?}", p);
}
Run Code Online (Sandbox Code Playgroud)

结果[2, 6, 24]就像我删除两个rev()s一样.两人rev()没有解决问题,他们只是"歼灭"对方.

这个任务是否可以在"调用链"样式中解决,而不使用for

mca*_*ton 8

实际上在文档中明确描述了此行为:

关于副作用的说明

map迭代器工具DoubleEndedIterator,这意味着你还可以map向后:

[...]

但是如果你的闭包有状态,那么向后迭代可能会以你不期望的方式行事.[...]

解决这个问题的方法是添加一个中介collect,以确保第二个rev不适用于Map:

fn main() {
    let input = vec![2, 3, 4];
    let mut prod = 1;
    let p: Vec<usize> = input
        .iter()
        .map(|v| {
            prod *= v;
            prod
        }).rev()
        .collect::<Vec<_>>()
        .into_iter()
        .rev()
        .collect();
    println!("{:?}", p);
}
Run Code Online (Sandbox Code Playgroud)

但这需要额外的分配.另一种方法是收集,然后反转:

fn main() {
    let input = vec![2, 3, 4];
    let mut prod = 1;
    let mut p: Vec<usize> = input
        .iter()
        .rev()
        .map(|v| {
            prod *= v;
            prod
        }).collect();
    p.reverse();

    println!("{:?}", p);
}
Run Code Online (Sandbox Code Playgroud)