Another use of Seq.fold: filtering
Last night, I had to filter a bunch of entries in a sequence down to only those items that had a particular characteristic. My thought process went like this: “I have a list of objects. When I’m done, I want a list of objects that have property X, discarding everything else. Ah-ha, I want to fold the sequence into a List.” I had some other constraints, such as the other library I was using was written in C# and used List
The code takes an array of some well-defined type and then filters on that type. In this case, the type has a formalized string * int tuple with names to make it useful from C#. You can place any well defined C# data type in place to get equivalent effects. For example, imagine sorting some Person or Order business object in your F# code looking for People named Fred or Orders over $100. In our case, we have the type MyType as a stand-in. The code filters on the quality of the object and returns only those instances with that quality.
#light
open System.Collections.Generic
type MyType(propA:string, propB:int) =
member this.PropA = propA
member this.PropB = propB
override this.ToString() = System.String.Format(“{0} {1}”, this.PropA, this.PropB)
let typeSeq =
[| new MyType(“red”, 4);
new MyType(“red”, 3);
new MyType(“blue”, 3);
new MyType(“blue”, 4);
new MyType(“blue”, 5);
|]
let filterVals theSeq propAValue =
theSeq |> Seq.fold(fun (acc:List
if (a.PropA = propAValue) then
acc.Add(a)
acc) (new List
printfn(“%A”) (filterVals typeSeq “red”)
printfn(“%A”) (filterVals typeSeq “blue”)
This code generates the following output in the interactive window:
seq [red 4; red 3]
seq [blue 3; blue 4; blue 5]
I like this syntax bit better than the LINQ syntax as I can achieve a typed collection in a trivial manner. I’m also enjoying the notion of moving away from explicit looping constructs and towards simple functions that just do the right thing for me.