In F#, imagine we have an array of bytes representing pixel data with three bytes per pixel in RGB order:
[| 255; 0; 0; //Solid red
0; 255; 0; //Solid green
0; 0; 255; //Solid blue
1; 72; 9;
34; 15; 155
... |]
I’m having a hard time knowing how to functionally operate on this data as-is, since a single item is really a consecutive block of three elements in the array.
So, I need to first group the triples in the array into something like this:
[|
[| 255; 0; 0 |];
[| 0; 255; 0 |];
[| 0; 0; 255 |];
[| 1; 72; 9 |];
[| 34; 15; 155 |]
... |]
Now, gathering up the triples into sub-arrays is easy enough to do with a for loop, but I’m curious–is there a functional way to gather up groups of array elements in F#? My ultimate goal is not simply to convert the data as illustrated above, but to solve the problem in a more declarative and functional manner. But I have yet to find an example of how to do this without an imperative loop.
kvb’s answer may not give you what you want.
Seq.windowedreturns a sliding window of values, e.g.,[1; 2; 3; 4]becomes[[1; 2; 3]; [2; 3; 4]]. It seems like you want it split into contiguous chunks. The following function takes a list and returns a list of triples ('T list -> ('T * 'T * 'T) list).Here’s the inverse:
EDIT
If you’re dealing with huge amounts of data, here’s a sequence-based approach
with constant memory use(all theoptions andtuples it creates have a negative impact on GC–see below for a better version):EDIT 2
ebb’s question about memory use prompted me to test and I found
toSeqTriplesto be slow and cause surprisingly frequent GCs. The following version fixes those issues and is almost 4x faster than the list-based version.This has relatively constant memory usage vs a list or array-based approach because a) if you have a
seqto start with the entire sequence doesn’t have to be slurped into a list/array; and b) it also returns a sequence, making it lazy, and avoiding allocating yet another list/array.