*Filtering* over a sequence of values omits values that do not meet certain criteria. *Mapping* over a sequence of values transforms each value into another value. What if you could do both at the same time—filter out unwanted values, but transform the ones that are left? You can with `Seq.choose`

.

Whereas `Seq.filter`

takes a predicate—a function that takes a value and returns a Boolean—`Seq.choose`

takes a function that takes a value and returns an `Option`

. If that `Option`

is `None`

, then `Seq.choose`

discards it. If it is `Some`

, then `Seq.choose`

extracts the value from the `Some`

and returns it as the next element in the output sequence.

let f = fun n -> match n % 2 with | 0 -> Some (n * n) | _ -> None let squaredEvens = seq [4..7] |> Seq.choose f // val squaredEvens : seq<int> = seq [16; 36]

The following graphic illustrates what is going on:

OK, so `Seq.choose`

performs a filter and a map all in one. Why not just call `Seq.filter`

and then `Seq.map`

? One example I’ve seen is when you’re pattern matching and destructuring and then only using one/some of the potential match cases. Perhaps you have a discriminated union representing orders that were either fulfilled or cancelled before fulfillment:

type Order = | Fulfilled of id : string * total : decimal | Cancelled of id : string * total : decimal

You’d like to know how many dollars you “lost” in cancelled orders. Use `Seq.choose`

to extract the dollar value of each cancelled order, and then sum them:

let orders = [ Fulfilled ("fef3356074b4", 28.50m) Fulfilled ("2605c9988f1d", 88.25m) Cancelled ("94edac47971f", 22.01m) Fulfilled ("2a1ff57b8f46", 39.30m) Fulfilled ("9ee0a3e3da3a", 27.97m) Cancelled ("db5dc439ad93", 99.49m) Fulfilled ("08d58811ed36", 53.72m) Cancelled ("63ebd07475ca", 93.66m) Cancelled ("12d16ae9c112", 7.79m) Fulfilled ("c5ecedaedb0e", 87.21m) ] let cancelledDollars = orders |> Seq.choose (function | Cancelled (_, dollars) -> Some dollars | _ -> None) |> Seq.sum // val cancelledDollars : decimal = 222.95M

## One reply on “F# Friday – Seq.choose”

[…] F# Friday – Seq.choose – Brad Collins […]