F# Friday – The Seq.chunkBySize Function

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 thought on “F# Friday – The Seq.chunkBySize Function”

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.