Cumulative map in rust

Hello All,

is there a way to use the previous item in the map to update the current one

something like

let iter = [1, 2, 3].iter()
     .map(|x| x*2)
     .something_like_map_with_prev(|v| v + v.prev)
     .collect<Vec<_>>()

assert!(iter == ["2", "6", "12"]);

thanks,

rich

You probably want fold

let iter = [1, 2, 3]
    .iter()
    .map(|x| x * 2)
    .fold(Vec::new(), |mut acc, i| {
        acc.push(acc.last().unwrap_or(0) + i);
        acc
    });

or something to that effect.

2 Likes

thank you so much, that was exactly what I was looking for

2 Likes

I first read this as "adjacent pairs", which would be https://docs.rs/itertools/0.10.1/itertools/trait.Itertools.html#method.tuple_windows

But it sounds more like "maintain some state during iteration", at which point you want https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.scan:

    let iter = [1, 2, 3]
        .iter()
        .map(|x| x * 2)
        .scan(0, |s, x| {
            *s += x;
            Some(*s)
        })
        .collect::<Vec<_>>();

    assert!(iter == [2, 6, 12]);

https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=21bdc854c3ce75413c6c2d06909a7491

2 Likes

Yoh could just use map

let prev = 0;
let iter = [1, 2, 3].iter()
     .map(|x| x*2)
     .map(|v| {
         let next = v + prev;
         prev = v;
         next
     })
     .collect<Vec<_>>()
1 Like

Just to advertise std::mem::* a bit more.

let mut prev = 0;
let iter = [1, 2, 3].iter()
     .map(|x| x*2)
     .map(|v| std::mem::replace(&mut prev, v) + v)
     .collect<Vec<_>>()
4 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.