Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Equivalent to Array.scan |> Array.skip 1, but without creating intermediate array?

Tags:

f#

The Array.scan function returns an array of length n+1, where n was the length of its input array, and whose first item is the initial state passed to Array.scan. E.g.,

[|1;2;3;4|] |> Array.scan (+) 0  // Returns [|0;1;3;6;10|]

However, I usually find that that isn't what I wanted: I wanted an array of length n, without the initial state being preserved in my output array. I could easily get this result by simply doing:

input |> Array.scan f initialState |> Array.skip 1

But this will create an intermediate array which is immediately thrown away. Is there a good way to get this result without creating an intermediate array? I could easily implement that myself:

let scanWithoutInitial f initState input =
    let result = Array.zeroCreate (Array.length input)
    let mutable state = initState
    for i = 0 to (Array.length input - 1) do
        state <- f state input.[i]
        result.[i] <- state
    result

However, this seems like a lot of work to reimplement something that I would think would be in the standard F# core library. Is there a function that I'm overlooking? Or am I the only one with this use case, and most people want the initial value as the first item of their Array.scan results?

like image 342
rmunn Avatar asked Mar 30 '17 15:03

rmunn


1 Answers

mapFold does exactly that:

Array.mapFold (fun acc x -> (acc + x, acc + x)) 0 [|1;2;3;4|] |> fst

For more of a brainteaser, ref this post.

like image 95
Funk Avatar answered Oct 20 '22 19:10

Funk