Another module function new with F# 4.0 is Seq.chunkBySize
(so new, in fact, that there is not even a hint of it on MSDN as of this writing, and hence the Github link). Seq.chunkBySize
groups a sequence’s elements into arrays (chunks) of a given size.
To take an example, if you have a sequence of twelve elements and call Seq.chunkBySize
to turn it into groups of three, you’ll get a sequence of four arrays, each three elements in size:
let xs = seq [1..12] let chunked = xs |> Seq.chunkBySize 3 // val chunked : seq<int []> = // seq [[|1; 2; 3|]; [|4; 5; 6|]; // [|7; 8; 9|]; [|10; 11; 12|]]
What happens if you use a chunk size that does not divide evenly into the size of your input sequence? No sweat! The last array just contains any remaining elements, however many they may be:
let xs = seq [1..10] let chunked = xs |> Seq.chunkBySize 3 // val chunked : seq<int []> = // seq [[|1; 2; 3|]; [|4; 5; 6|]; // [|7; 8; 9|]; [|10|]]
Where is this useful? Well, you can take my paging example from my F# Friday post on Seq.skip
and make it slightly clearer without the (page - 1) * perPage
arithmetic:
type Book = { Title : string Author : string } let books = seq [ { Title = "Wuthering Heights" Author = "Emily Bronte" } { Title = "Jane Eyre" Author = "Charlotte Bronte" } { Title = "Agnes Grey" Author = "Anne Bronte" } { Title = "The Scarlet Letter" Author = "Nathaniel Hawthorne" } { Title = "Silas Marner" Author = "George Eliot" } { Title = "1984" Author = "George Orwell" } { Title = "Billy Budd" Author = "Herman Melville" } { Title = "Moby Dick" Author = "Herman Melville" } { Title = "The Great Gatsby" Author = "F. Scott Fitzgerald" } { Title = "Tom Sawyer" Author = "Mark Twain" } ] let perPage = 3 let page = 3 let records = books |> Seq.chunkBySize perPage |> Seq.skip (page - 1) |> Seq.head // val records : Book [] = // [|{Title = "Billy Budd"; // Author = "Herman Melville";}; // {Title = "Moby Dick"; // Author = "Herman Melville";}; // {Title = "The Great Gatsby"; // Author = "F. Scott Fitzgerald";}|]
This time, instead of having to calculate the number of elements to skip in order to skip n pages, you first use Seq.chunkBySize
to turn the sequence into a paged recordset; each “page” is n records long. Then skip page - 1
pages in order to get to the page of records you want. Finally, calling Seq.head
is necessary because, remember, Seq.chunkBySize
turns a flat sequence into a sequence of arrays.
One final note: the Array
and List
modules also contain a chunkBySize
function in F# 4.0.
One reply on “F# Friday – The Seq.chunkBySize Function”
[…] F# Friday – The Seq.chunkBySize Function – Brad Collins […]