All these solutions are assuming that it is fine to re-enumerate the sequence, i.e. by truncating once and then skipping. That might be an OK assumption for small, in-memory data-sets, but an IEnumerable
doesn't have to allow multiple enumeration, and it can be expensive. As pointed out pointed out by Tomas Petricek on that other question, due to the forward-only nature of sequences, whenever you "back up" over a sequence like this it actually has to enumerate the entire thing from the beginning.
All these solutions are assuming that it is fine to re-enumerate the sequence, i.e. by truncating once and then skipping. That might be an OK assumption for small, in-memory data-sets, but an IEnumerable
doesn't have to allow multiple enumeration, and it can be expensive. As pointed out by Tomas Petricek on that other question, due to the forward-only nature of sequences, whenever you "back up" over a sequence like this it actually has to enumerate the entire thing from the beginning.
All these solutions are assuming that it is fine to re-enumerate the sequence, i.e. by truncating once and then skipping. That might be an OK assumption for small, in-memory data-sets, but an IEnumerable
doesn't have to allow multiple enumeration, and it can be expensive. As pointed out by Tomas Petricek on that other question, due to the forward-only nature of sequences, whenever you "back up" over a sequence like this it actually has to enumerate the entire thing from the beginning.
Seq.foldunfold Solution
let segmented (size:int) (source:'t[]) =
let maxPos = source.Length - 1
[| for pos in 0 .. size .. maxPos ->
source.[pos .. min (pos + size - 1) maxPos] |]
Seq.fold Solution
let segmented (size:int) (source:'t[]) =
let maxPos = source.Length - 1
[| for pos in 0 .. size .. maxPos ->
source.[pos .. min (pos + size - 1) maxPos] |]
Seq.unfold Solution
let segmented (size:int) (source:'t[]) =
let maxPos = source.Length - 1
[| for pos in 0 .. size .. maxPos ->
source.[pos .. min (pos + size - 1) maxPos] |]
Mutability is somewhat frowned upon in functional languagesFunctional-first style tends to prefer immutability over mutability, so the fact that you're using ref
signifiescan sometimes signify that the code could be more idiomatic.
But perhaps a sequence isn't the best choice of data types for input into this function. If the data is already in memory, you have a choice of turning it into a list or an array. Arrays are especially nice for this problem due to their support for slicing. Here's a solution that uses an array for source
arrays instead of sequences:
let rec chop segmentSize source =
segmented if(size:int) (source:'t[]) = [||] then Seq.empty else
let lenmaxPos = Arraysource.lengthLength source- |>1
min segmentSize
[| for letpos segmentin =0 source.[. size .. lenmaxPos - 1]>
let rest = source.[len[pos ..]
min (pos + Seq.appendsize [Seq.ofArray- segment]1) (chopmaxPos] segmentSize rest) |]
Mutability is somewhat frowned upon in functional languages, so the fact that you're using ref
signifies that the code could be more idiomatic.
But perhaps a sequence isn't the best choice of data types for input into this function. If the data is already in memory, you have a choice of turning it into a list or an array. Arrays are especially nice for this problem due to their support for slicing. Here's a solution that uses an array for source
:
let rec chop segmentSize source =
if source = [||] then Seq.empty else
let len = Array.length source |> min segmentSize
let segment = source.[.. len - 1]
let rest = source.[len ..]
Seq.append [Seq.ofArray segment] (chop segmentSize rest)
Functional-first style tends to prefer immutability over mutability, so the fact that you're using ref
can sometimes signify that the code could be more idiomatic.
But perhaps a sequence isn't the best choice of data types for input into this function. If the data is already in memory, you have a choice of turning it into a list or an array. Arrays are especially nice for this problem due to their support for slicing. Here's a solution that uses arrays instead of sequences:
let segmented (size:int) (source:'t[]) =
let maxPos = source.Length - 1
[| for pos in 0 .. size .. maxPos ->
source.[pos .. min (pos + size - 1) maxPos] |]