Home

F# Lists: Choosing a Sub-List

   

Description

To create a sub-list, you can apply a condition to the items of an existing list so that the elements that respond to the condition would be selected and added to the new list. To assist you with this, the List module is equipped with a function named choose. Its signature is:

List.choose : ('T -> 'U option) -> 'T list -> 'U list

This function takes two arguments. The first is a function that includes a matching conditional statement. The second argument is the list on which the condition will be applied. Here is an example:

open System
open System.IO
open System.Drawing
open System.Windows.Forms
open System.Collections.Generic
open System.Runtime.Serialization.Formatters.Binary

type StoreItem = {
    ItemNumber  : int
    Category    : string
    SubCategory : string
    ItemName    : string
    ItemSize    : string
    UnitPrice   : float
    DaysInStore : int
    Status      : string }

type SaleItem(number, category, subcat, name, size, price, days) =
    let nbr = ref number
    let cat = ref category
    let sub = ref subcat
    let nm  = ref name
    let sz  = ref size
    let prc = ref price
    let ds  = ref days
    
    member this.ItemNumber  with get() = !nbr and set(value) = nbr := value
    member this.Category    with get() = !cat and set(value) = cat := value
    member this.SubCategory with get() = !sub and set(value) = sub := value
    member this.ItemName    with get() = !nm  and set(value) = nm  := value
    member this.ItemSize    with get() = !sz  and set(value) = sz  := value
    member this.UnitPrice   with get() = !prc and set(value) = prc := value    
    member this.DaysInStore with get() = !ds  and set(value) = ds  := value
    
    member this.DiscountRate with get() =
                                    if !ds >= 60 then 50.00
                                    elif !ds >= 30 then 35.00
                                    elif !ds >= 15 then 10.00
                                    else 0.00
    member this.DiscountAmount with get() = !prc * this.DiscountRate / 100.00    
    member this.MarkedPrice    with get() = this.UnitPrice - this.DiscountAmount
    new() = SaleItem(0, "", "", "", "", 0.00, 0)
   
let mutable storeItems = new List<StoreItem>()
let mutable salesItems = []

let departmentStore = new Form(ClientSize = new Size(865, 390),
                               MaximizeBox = false, Text = "Department Store", 
                               StartPosition = FormStartPosition.CenterScreen)

let lvwStoreItems : ListView = new ListView(GridLines = true, View = View.Details, FullRowSelect = true, Location = new Point(12, 12), Size = new System.Drawing.Size(840, 330))
let mutable col = lvwStoreItems.Columns.Add("Item #", 60)
col <- lvwStoreItems.Columns.Add("Category", 65)
col <- lvwStoreItems.Columns.Add("Sub-Category", 80)
col <- lvwStoreItems.Columns.Add("Item Name", 220)
col <- lvwStoreItems.Columns.Add("Item Size", 60)
col <- lvwStoreItems.Columns.Add("Unit Price", 60, HorizontalAlignment.Right)
col <- lvwStoreItems.Columns.Add("Days in Store", 75, HorizontalAlignment.Right)
col <- lvwStoreItems.Columns.Add("Disc Rate", 65, HorizontalAlignment.Right)
col <- lvwStoreItems.Columns.Add("Disc Amt", 60, HorizontalAlignment.Right)
col <- lvwStoreItems.Columns.Add("Marked Price", 75, HorizontalAlignment.Right)

departmentStore.Controls.Add lvwStoreItems(**)

let showStoreItems items =
    lvwStoreItems.Items.Clear()

    List.iter (fun (item : SaleItem) ->
        let mutable lviStoreItem = new ListViewItem(sprintf "%i" item.ItemNumber)
        lviStoreItem.SubItems.Add item.Category |> ignore
        lviStoreItem.SubItems.Add item.SubCategory |> ignore
        lviStoreItem.SubItems.Add item.ItemName |> ignore
        lviStoreItem.SubItems.Add item.ItemSize |> ignore
        lviStoreItem.SubItems.Add(sprintf "%0.02f" item.UnitPrice) |> ignore
        lviStoreItem.SubItems.Add(sprintf "%i" item.DaysInStore) |> ignore
        if item.DiscountRate <= 0.00 then
            lviStoreItem.SubItems.Add "" |> ignore
        else
            lviStoreItem.SubItems.Add(sprintf "%0.0f%c" item.DiscountRate '%') |> ignore
        if item.DiscountRate <= 0.00 then
            lviStoreItem.SubItems.Add "" |> ignore
        else
            lviStoreItem.SubItems.Add(sprintf "%0.02f" item.DiscountAmount) |> ignore
        lviStoreItem.SubItems.Add(sprintf "%0.02f" item.MarkedPrice) |> ignore
        lvwStoreItems.Items.Add lviStoreItem |> ignore) items

let departmentStoreLoad _ =
    let bfStoreItems = new BinaryFormatter()
    let strStoreItemsFile : string =  @"C:\Fun Department Store\StoreItems.sis"

    use fsStoreItems = new FileStream(strStoreItemsFile, FileMode.Open, FileAccess.Read, FileShare.Read)
    storeItems <- bfStoreItems.Deserialize(fsStoreItems) :?> List<StoreItem>
    fsStoreItems.Close()

    salesItems <- [ for item in storeItems do if item.Status = "Flawless" then yield new SaleItem(item.ItemNumber, item.Category, item.SubCategory, item.ItemName, item.ItemSize, item.UnitPrice, item.DaysInStore) ]
    showStoreItems salesItems
departmentStore.Load.Add departmentStoreLoad

let btnShowAllItems = new Button(Location = new Point(12, 355), Width = 150, Text = "Show all Items")
departmentStore.Controls.Add btnShowAllItems

let btnShowAllItemsClick _ = 
    showStoreItems salesItems
btnShowAllItems.Click.Add btnShowAllItemsClick

let btnWomenItems = new Button(Location = new Point(180, 355), Width = 150, Text = "Show Women Items")
departmentStore.Controls.Add btnWomenItems

let btnWomenItemsClick _ =
    let womenItems = List.choose (fun (item : SaleItem) ->
            match item.Category with
            | "Women" -> Some(item)
            | _ -> None) salesItems
    showStoreItems womenItems
btnWomenItems.Click.Add btnWomenItemsClick

let btnClose = new Button(Left = 780, Top = 355, Text = "Close")
let btnCloseClick e =
    departmentStore.Close()
btnClose.Click.Add btnCloseClick
departmentStore.Controls.Add btnClose

[<EntryPoint>]
let main argv =
    Application.Run departmentStore
    0

This would produce:

Choosing a Sub-List

Choosing a Sub-List

An alternative is to apply the list to a call to this function. Here is an example:

let btnWomenItemsClick _ =
    let womenItems = salesItems |> List.choose (fun (item : SaleItem) ->
            match item.Category with
            | "Women" -> Some(item)
            | _ -> None)
    showStoreItems womenItems
     
 

Home Copyright © 2009-2015, FunctionX Home