rmunn
rmunn

Reputation: 36678

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

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?

Upvotes: 7

Views: 526

Answers (2)

citykid
citykid

Reputation: 11060

[|1;2;3;4|] |> Seq.scan (+) 0 |> Seq.skip 1 |> Seq.toArray

Upvotes: 0

Funk
Funk

Reputation: 11201

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.

Upvotes: 4

Related Questions