Categories
Tech

F# Friday – The partition Function

The filter function takes a collection and a predicate and returns only the items in a collection that meet the predicate. It discards the ones that don’t.

Well, what if you want to retain all the items in the collection, but you just want them separated into two groups–the sheep from goats, as it were? That’s where partition comes in. The partition operation takes a collection and a predicate, just as filter does, but instead of tossing the items that don’t meet the predicate, partition returns a second collection along with the first: one containing all the items that meet the predicate and one containing all the rest.

Maybe you run a business, and once per quarter, you want to send a message to all your customers. You send a thank you note to the customers that have made a purchase in the last quarter. To the customers who have not, you send a we-miss-you note, perhaps containing a coupon. So then, you need to partition your customer list:

A list of customers, each with a LastPurchase field that is the date of the customer's last purchase, partitioned into two lists. The first list is all customers who have made a purchase in the last three months while the other list contains customers who have not made a purchase in the last three months.
Partitioning a List of Customers Based on the Date of the Latest Purchase

Here is the Customer type:

type Customer(name : string, email : string, latestPurchase : DateTime) =
    member x.Name = name
    member x.Email = email
    member x.LatestPurchase = latestPurchase
    override x.ToString() = 
        latestPurchase.ToString("dd MMM yyyy")
        |> sprintf "Customer(%s, %s, %s)" name email

Now given a list of customers, here is how you partition that list into those who have made recent purchases and those who have not:

let customers = [
    Customer("Bob", "bob@bob.com", DateTime.Parse "5 Jun 2015")
    Customer("Barb", "barb@barbara.com", DateTime.Parse "15 May 2015")
    Customer("Chuck", "chuck@charles.com", DateTime.Parse "26 Jan 2015")
    Customer("Charlie", "charlie@charlotte.com", DateTime.Parse "1 Mar 2015")
    Customer("Dan", "dan@dan.com", DateTime.Parse "21 Dec 2014")
    Customer("Deb", "deb@deborah.com", DateTime.Parse "24 Jan 2015")
    Customer("Ed", "ed@theodore.com", DateTime.Parse "15 Mar 2015")
    Customer("Elle", "elle@elle.com", DateTime.Parse "15 Jun 2015")
]

let threeMosAgo = DateTime.Now.AddMonths -3
let recent, distant =
    customers
    |> List.partition (fun c -> c.LatestPurchase > threeMosAgo)
// val recent : Customer list =
//   [Customer(Bob, bob@bob.com, 05 Jun 2015);
//    Customer(Barb, barb@barbara.com, 15 May 2015);
//    Customer(Elle, elle@elle.com, 15 Jun 2015)]
// val distant : Customer list =
//   [Customer(Chuck, chuck@charles.com, 26 Jan 2015);
//    Customer(Charlie, charlie@charlotte.com, 01 Mar 2015);
//    Customer(Dan, dan@dan.com, 21 Dec 2014);
//    Customer(Deb, deb@deborah.com, 24 Jan 2015);
//    Customer(Ed, ed@theodore.com, 15 Mar 2015)]

Now you can send that thank you note to each of the customers in the recent list and a miss-you note to each customer in the distant list.

One reply on “F# Friday – The partition 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.