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)