Home

F# Collections: Partitioning a List

   

Description

Partitioning a list consists of creating two lists derived from an existing one. To do this, you apply a condition to an existing list. The items that respond to the condition are put in a new list. The items that don't respond to the condition are put in another new list.

To support list partitioning, the List module provides a function named partition. Its signature is:

List.partition : ('T -> bool) -> 'T list -> 'T list * 'T list

This function takes a function and a list as arguments. The function argument applies a condition to all members of the list. The function returns two lists. You can get the return value as two values or as a pair. Here is an example:

open System
open System.Windows.Forms

type OccupancyStatus =
| Other
| Available
| Occupied
| NeedsRepair

type Apartment = {
    UnitNumber      : string
    Bedrooms        : int
    Bathrooms       : float
    SecurityDeposit : int
    MonthlyRate     : int
    Status          : OccupancyStatus }

let apartments = [
    { UnitNumber = "101"; Bedrooms = 2; Bathrooms = 2.00; SecurityDeposit = 650; MonthlyRate = 1150; Status = OccupancyStatus.Available   }
    { UnitNumber = "102"; Bedrooms = 1; Bathrooms = 1.00; SecurityDeposit = 500; MonthlyRate =  950; Status = OccupancyStatus.NeedsRepair }
    { UnitNumber = "103"; Bedrooms = 1; Bathrooms = 1.00; SecurityDeposit = 500; MonthlyRate =  925; Status = OccupancyStatus.Available   }
    { UnitNumber = "104"; Bedrooms = 3; Bathrooms = 2.00; SecurityDeposit = 850; MonthlyRate = 1350; Status = OccupancyStatus.Occupied    }
    { UnitNumber = "105"; Bedrooms = 2; Bathrooms = 1.00; SecurityDeposit = 550; MonthlyRate = 1150; Status = OccupancyStatus.Available   }
    { UnitNumber = "106"; Bedrooms = 3; Bathrooms = 1.50; SecurityDeposit = 950; MonthlyRate = 1425; Status = OccupancyStatus.NeedsRepair }
    { UnitNumber = "107"; Bedrooms = 1; Bathrooms = 1.00; SecurityDeposit = 500; MonthlyRate =  950; Status = OccupancyStatus.Occupied    }
    { UnitNumber = "108"; Bedrooms = 2; Bathrooms = 1.00; SecurityDeposit = 550; MonthlyRate = 1150; Status = OccupancyStatus.Occupied    }
 ]

let (ready, not) = List.partition (fun (apart : Apartment) -> apart.Status = OccupancyStatus.Available) apartments

let apartmentsListing = new Form(Width = 355, Height = 310, Text = "Apartments Listing", MaximizeBox = false)

apartmentsListing.Controls.Add(new Label(Left = 12, Top = 12, Width = 200, Height = 13, Text = "Apartments - Ready to Rent"))

let lbxReadyApartments = new ListBox(Left = 12, Top = 32, Width = 320, Height = 98)

lbxReadyApartments.Items.Add("\t\t\tMonthly") |> ignore
lbxReadyApartments.Items.Add("Unit # Beds\tBaths\tRent\tDeposit\tStatus") |> ignore
lbxReadyApartments.Items.Add("----------------------------------------------------------------------------------------------------") |> ignore
for apart in ready do
    lbxReadyApartments.Items.Add(sprintf "%s\t%i\t%.2f\t%d\t%d\t%A" apart.UnitNumber apart.Bedrooms apart.Bathrooms apart.MonthlyRate apart.SecurityDeposit apart.Status) |> ignore
lbxReadyApartments.Items.Add("----------------------------------------------------------------------------------------------------") |> ignore

apartmentsListing.Controls.Add lbxReadyApartments

apartmentsListing.Controls.Add(new Label(Left = 12, Top = 135, Width = 200, Height = 13, Text = "Apartments - Not Ready for Rent"))

let lbxNotReadyApartments = new ListBox(Left = 12, Top = 152, Width = 320, Height = 130)

lbxNotReadyApartments.Items.Add("\t\t\tMonthly") |> ignore
lbxNotReadyApartments.Items.Add("Unit # Beds\tBaths\tRent\tDeposit\tStatus") |> ignore
lbxNotReadyApartments.Items.Add("----------------------------------------------------------------------------------------------------") |> ignore
for apart in not do
    lbxNotReadyApartments.Items.Add(sprintf "%s\t%i\t%.2f\t%d\t%d\t%A" apart.UnitNumber apart.Bedrooms apart.Bathrooms apart.MonthlyRate apart.SecurityDeposit apart.Status) |> ignore
lbxNotReadyApartments.Items.Add("----------------------------------------------------------------------------------------------------") |> ignore

apartmentsListing.Controls.Add lbxNotReadyApartments

do Application.Run apartmentsListing
     
 

This would produce:

Partitioning a List

Notice that the List.partition() function returns a tuple pair whose two elements are a list each. If one of both tuple members holds a list whose members can be segmented based on certain criterion, you can call the function on that member to get another tuple with sub-lists. Here is an example:

open System
open System.Windows.Forms

type OccupancyStatus =
| Other
| Available
| Occupied
| NeedsRepair

type Apartment = {
    UnitNumber      : string
    Bedrooms        : int
    Bathrooms       : float
    SecurityDeposit : int
    MonthlyRate     : int
    Status          : OccupancyStatus }

let apartments = [
    { UnitNumber = "101"; Bedrooms = 2; Bathrooms = 2.00; SecurityDeposit = 650; MonthlyRate = 1150; Status = OccupancyStatus.Available   }
    { UnitNumber = "102"; Bedrooms = 1; Bathrooms = 1.00; SecurityDeposit = 500; MonthlyRate =  950; Status = OccupancyStatus.NeedsRepair }
    { UnitNumber = "103"; Bedrooms = 1; Bathrooms = 1.00; SecurityDeposit = 500; MonthlyRate =  925; Status = OccupancyStatus.Available   }
    { UnitNumber = "104"; Bedrooms = 3; Bathrooms = 2.00; SecurityDeposit = 850; MonthlyRate = 1350; Status = OccupancyStatus.Occupied    }
    { UnitNumber = "105"; Bedrooms = 2; Bathrooms = 1.00; SecurityDeposit = 550; MonthlyRate = 1150; Status = OccupancyStatus.Available   }
    { UnitNumber = "106"; Bedrooms = 3; Bathrooms = 1.50; SecurityDeposit = 950; MonthlyRate = 1425; Status = OccupancyStatus.NeedsRepair }
    { UnitNumber = "107"; Bedrooms = 1; Bathrooms = 1.00; SecurityDeposit = 500; MonthlyRate =  950; Status = OccupancyStatus.Occupied    }
    { UnitNumber = "108"; Bedrooms = 2; Bathrooms = 1.00; SecurityDeposit = 550; MonthlyRate = 1150; Status = OccupancyStatus.Occupied    }
 ]

//let (ready, not) = List.partition (fun (apart : Apartment) -> apart.Status = OccupancyStatus.Available) apartments
let (notAvailable, available) = List.partition (fun (apart : Apartment) -> apart.Status <> OccupancyStatus.Available) apartments
let (occupied, needRepair) = List.partition (fun (apart : Apartment) -> apart.Status = OccupancyStatus.Occupied) notAvailable

let apartmentsListing = new Form(Width = 355, Height = 395, Text = "Apartments Listing", MaximizeBox = false)

apartmentsListing.Controls.Add(new Label(Left = 12, Top = 12, Width = 200, Height = 13, Text = "Apartments - Available"))

let lbxReadyApartments = new ListBox(Left = 12, Top = 32, Width = 320, Height = 98)

lbxReadyApartments.Items.Add("\t\t\tMonthly") |> ignore
lbxReadyApartments.Items.Add("Unit # Beds\tBaths\tRent\tDeposit\tStatus") |> ignore
lbxReadyApartments.Items.Add("----------------------------------------------------------------------------------------------------") |> ignore
for apart in available do
    lbxReadyApartments.Items.Add(sprintf "%s\t%i\t%.2f\t%d\t%d\t%A" apart.UnitNumber apart.Bedrooms apart.Bathrooms apart.MonthlyRate apart.SecurityDeposit apart.Status) |> ignore
lbxReadyApartments.Items.Add("----------------------------------------------------------------------------------------------------") |> ignore

apartmentsListing.Controls.Add lbxReadyApartments

apartmentsListing.Controls.Add(new Label(Left = 12, Top = 135, Width = 200, Height = 13, Text = "Apartments - Occupied"))

let lbxNotReadyApartments = new ListBox(Left = 12, Top = 152, Width = 320, Height = 100)

lbxNotReadyApartments.Items.Add("\t\t\tMonthly") |> ignore
lbxNotReadyApartments.Items.Add("Unit # Beds\tBaths\tRent\tDeposit\tStatus") |> ignore
lbxNotReadyApartments.Items.Add("----------------------------------------------------------------------------------------------------") |> ignore
for apart in occupied do
    lbxNotReadyApartments.Items.Add(sprintf "%s\t%i\t%.2f\t%d\t%d\t%A" apart.UnitNumber apart.Bedrooms apart.Bathrooms apart.MonthlyRate apart.SecurityDeposit apart.Status) |> ignore
lbxNotReadyApartments.Items.Add("----------------------------------------------------------------------------------------------------") |> ignore

apartmentsListing.Controls.Add lbxNotReadyApartments

apartmentsListing.Controls.Add(new Label(Left = 12, Top = 255, Width = 200, Height = 13, Text = "Apartments - Need Repair"))

let lbxNeedRepair = new ListBox(Left = 12, Top = 272, Width = 320, Height = 90)

lbxNeedRepair.Items.Add("\t\t\tMonthly") |> ignore
lbxNeedRepair.Items.Add("Unit # Beds\tBaths\tRent\tDeposit\tStatus") |> ignore
lbxNeedRepair.Items.Add("----------------------------------------------------------------------------------------------------") |> ignore
for apart in needRepair do
    lbxNeedRepair.Items.Add(sprintf "%s\t%i\t%.2f\t%d\t%d\t%A" apart.UnitNumber apart.Bedrooms apart.Bathrooms apart.MonthlyRate apart.SecurityDeposit apart.Status) |> ignore
lbxNeedRepair.Items.Add("----------------------------------------------------------------------------------------------------") |> ignore

apartmentsListing.Controls.Add lbxNeedRepair

do Application.Run apartmentsListing

This would produce:

Partitioning a List

   
   
 

Home Copyright © 2009-2015, FunctionX Home