This article is to provide you with some basic examples of collection manipulation in F# run from a console application in .NET 6. The examples are drawn heavily from a series of exercises in Stylish F# 6: Crafting Elegant Functional Code for .NET 6, 2nd Edition, 2021 by Kit Eason.
In order to run the examples you will need to add some initial utility functions and types to the top of your program.fs file.
type Car =
{ Model : string
Price : decimal }
type PriceBand = | Cheap | Medium | Expensive
module FakeData =
let private random = System.Random(Seed = 1)
/// Make an array of 'count' number of random houses.
let getRandomArrayOfCars (count: int) =
Array.init count (fun i ->
{ Model = $"Model %i{i+1}"
Price = random.Next(10_000, 150_000) |> decimal })
/// Try to get the distance to the nearest garage.
/// While the 'Car' parameter is not used we add it to change the signature
/// Allowing us to pipe into it later with a Car object
let tryGetDistanceToGarage (car: Car) =
let dist = random.Next(30) |> double
if dist < 20 then
Some dist
else
None
// Return a price band based on price.
let getPriceCategory (price : decimal) =
if price < 40_000m then
Cheap
elif price < 100_000m then
Medium
else
Expensive
module Array =
let inline tryAverageBy f (a : 'T[]) =
if a.Length = 0 then
None
else
let average = a |> Array.averageBy f |> decimal
System.Math.Round(average, 2) |> Some
Then you can add the below examples and execute them with dotnet run.
// Transforming Data Items
let getCarListing =
printfn "\n------ TRANSFORMING DATA ------"
FakeData.getRandomArrayOfCars 3
|> Array.map (fun h ->
printfn $"Model: {h.Model} - Price: {h.Price}")
// Calculating an Average
let getAverageCarPrice =
printfn "\n-------- AVERAGE PRICE --------"
let price = FakeData.getRandomArrayOfCars 10
|> Array.averageBy (fun c -> c.Price)
printfn $"Average price: {price}"
// Selecting Based on Condition, Order and iteration
let getExpensiveCars =
printfn "\n------- EXPENSIVE CARS --------"
FakeData.getRandomArrayOfCars 10
|> Array.filter (fun c -> c.Price > 100_000m)
|> Array.sortByDescending (fun c -> c.Price)
|> Array.iter (fun c ->
printfn $"Model: {c.Model} - Price: {c.Price}")
// Finding a Single Element
let getCarWithDistanceToGarage =
printfn "\n- CAR WITH DISTANCE TO GARAGE -"
let result = FakeData.getRandomArrayOfCars 1
|> Array.tryPick (fun c ->
match c |> FakeData.tryGetDistanceToGarage with
| Some d -> Some(c, d)
| None -> None)
printfn $"{result}"
let getCarsByPriceCategory =
printfn "\n--- CAR WITH PRICE CATEGORY ---"
let result = FakeData.getRandomArrayOfCars 6
|> Array.groupBy (fun c -> c.Price |> FakeData.getPriceCategory)
|> Array.map (fun group ->
let category, cars = group
category, cars |> Array.sortBy (fun c -> c.Price))
printfn $"{result[0]}"
let tryGetAverageCarPriceOver100K =
printfn "\n--- AVERAGE PRICE OVER 100K ---"
let result = FakeData.getRandomArrayOfCars 20
|> Array.filter (fun h -> h.Price > 100_000m)
|> Array.tryAverageBy (fun h -> h.Price)
printfn $"{result}"
Output
------ TRANSFORMING DATA ------
Model: Model 1 - Price: 44813
Model: Model 2 - Price: 25504
Model: Model 3 - Price: 75381
-------- AVERAGE PRICE --------
Average price: 73004.4
------- EXPENSIVE CARS --------
Model: Model 1 - Price: 148567
Model: Model 8 - Price: 142968
Model: Model 6 - Price: 108595
Model: Model 7 - Price: 108251
Model: Model 2 - Price: 105497
Model: Model 3 - Price: 101684
- CAR WITH DISTANCE TO GARAGE -
Some(({ Model = "Model 1"
Price = 63475M }, 15))
--- CAR WITH PRICE CATEGORY ---
(Cheap, Program+Car[])
--- AVERAGE PRICE OVER 100K ---
Some(120609.44)
Top comments (0)