rust-itertools / itertools

Extra iterator adaptors, iterator methods, free functions, and macros.
https://docs.rs/itertools/
Apache License 2.0
2.72k stars 309 forks source link

Map with cache #631

Open malthe opened 2 years ago

malthe commented 2 years ago

I have found it useful to have a map that is able to hold a cached value, which can be used during the iteration.

The name fold_map comes to mind because it can be implemented using fold but works like a map.

In the example below, a vector of booleans is mapped such that values around a true value are also true.

let v = vec![true, false, false, false, true, false, true];
let i = v.into_iter().enumerate().circular_tuple_windows().fold_map(None, |prev, (curr, next)| {
    let result = curr.1 || (next.0 > curr.0 && next.1) || if let Some(prev) = prev {
        (prev.0 < curr.0 && prev.1) || 
    } else { 
        false
    };
    (curr, result)
}); 

This would yield an iterator for [true, true, false, true, true, true, true].

And a smaller, somewhat random example:

let v = vec![1, 2, 3, 4];
let i = v.iter().fold_map(None, |p, n| (Some(n), n + p.unwrap_or(0))) 

This would yield an iterator for [1, 3, 5, 7].

scottmcm commented 2 years ago

If you need a map with some internal state, maybe you want https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.scan ?

malthe commented 2 years ago

@scottmcm scan returns that internal state as the result – what I am looking for is to still return the result of the map so to speak (and simply discarding the internal state after iteration completes).