F# Map
last modified September 20, 2023
In this article we show how to work with a Map collection in F#.
A map is is an immutable collection of key/value pairs. The maps are accessed by a key.
F# Map simple example
The following is a simple map example.
let words = Map [1, "book"; 2, "sky"; 3, "work"; 4, "cloud"] printfn "%A" words printfn "%s" words[1] printfn "%s" words[4]
We have a map of words. The keys are integers and the values are strings.
let words = Map [1, "book"; 2, "sky"; 3, "work"; 4, "cloud"]
The keys are separated from values with a comma character. The pairs are separated with a semicolon.
printfn "%A" words
With the %A
format specifier, we pretty-print the map.
printfn "%s" words[1] printfn "%s" words[4]
We print the elements with index 1 and 4.
λ dotnet fsi main.fsx map [(1, "book"); (2, "sky"); (3, "work"); (4, "cloud")] book cloud
F# Map size
The Count
property returns the number of pairs in the map.
let words = Map [1, "book"; 2, "sky"; 3, "work"; 4, "cloud"] let n = words.Count printfn $"The map has {n} elements"
The example prints the number of elements int he map.
F# Map iteration
In the next example, we loop over the elements of a Map.
let words = Map [1, "book"; 2, "sky"; 3, "work"; 4, "cloud"] printfn "%A" words words |> Map.iter (fun k v -> printfn ($"{k}: {v}")) for key in words.Keys do printfn "%d" key for value in words.Values do printfn "%s" value for e in words do printfn $"{e.Key}: {e.Value}"
We provide two basic ways of iteration: functional and imperative. The
functional uses the Map.iter
function, while the imperative uses
for loops.
words |> Map.iter (fun k v -> printfn ($"{k}: {v}"))
The Map.iter
is the functional way of looping over map elements.
for key in words.Keys do printfn "%d" key
We loop over the keys of the map.
for value in words.Values do printfn "%s" value
We iterate over the values of the map.
for e in words do printfn $"{e.Key}: {e.Value}"
We iterate over the pairs of the map.
λ dotnet fsi main.fsx map [(1, "book"); (2, "sky"); (3, "work"); (4, "cloud")] 1: book 2: sky 3: work 4: cloud 1 2 3 4 book sky work cloud 1: book 2: sky 3: work 4: cloud
F# Map.filter
We can filter map elements with Map.filter
.
let words = Map [ 1, "book" 2, "sky" 3, "work" 4, "cloud" 5, "water" 6, "war" ] words |> Map.filter (fun _ v -> v.Contains "w") |> Map.values |> Seq.iter (printfn "%s")
In the program, we find out all values which start with 'w'.
words |> Map.filter (fun _ v -> v.Contains "w") |> Map.values |> Seq.iter (printfn "%s")
We pass a predicate lambda to the filter method; it checks if the value
contains 'w'. The result is passed to the Map.values
to extract
all values. Then the values are iterated and printed to the console.
λ dotnet fsi main.fsx work water war
F# Map Remove
The Remove
method returns a new map from which the specified pair
is removed.
let words = Map [ 1, "book" 2, "sky" 3, "work" 4, "cloud" 5, "water" 6, "war" ] let res = words.Remove 1 printfn "%A" res printfn "%A" words
In the example, we remove the element with key 1. The original map is not changed.
λ dotnet fsi main.fsx map [(2, "sky"); (3, "work"); ... (6, "war")] map [(1, "book"); (2, "sky"); (3, "work"); ... (6, "war")]
F# Map Add
With Add
, we add a new element to the map.
let words = Map [ 1, "book" 2, "sky" 3, "work" 4, "cloud" 5, "water" 6, "war" ] let res = Map.add 7 "falcon" words printfn "%A" res printfn "%A" words
We add a new pair to the map.
λ dotnet fsi main.fsx map [(1, "book"); (2, "sky"); ... (6, "war"); (7, "falcon")] map [(1, "book"); (2, "sky"); ... (6, "war")]
F# Map.empty
We can create an empty map with Map.empty
and add new elements
with Add
.
type User = { Name: string Occupation: string } let users = Map.empty. Add(1, {Name="John Doe"; Occupation="gardener"}). Add(2, {Name="Roger Roe"; Occupation="driver"}). Add(3, {Name="Lucy Smith"; Occupation="teacher"}). Add(4, {Name="Tom Jones"; Occupation="programmer"}) users |> Map.iter (fun k v -> printfn $"{k}: {v}")
Utilizing Map.empty
, we create a map of users.
λ dotnet fsi main.fsx 1: { Name = "John Doe" Occupation = "gardener" } 2: { Name = "Roger Roe" Occupation = "driver" } 3: { Name = "Lucy Smith" Occupation = "teacher" } 4: { Name = "Tom Jones" Occupation = "programmer" }
F# list of maps
In the next example, we define a list of maps.
let fruits1 = Map [ "oranges", 2; "bananas", 3 ] let fruits2 = Map [ "plums", 4; "kiwis", 5 ] let all = [ Map[1, fruits1]; Map[2, fruits2] ] all |> List.iter (Map.iter (fun k v -> printfn $"{k} {v}")) printfn "-------------------" for nested in all do for e in nested do printfn $"{e.Key} {e.Value}"
We define two maps and insert them into a list. The list is then iterated in declarative and imperative way.
all |> List.iter (Map.iter (fun k v -> printfn $"{k} {v}"))
We iterate of the list of maps declaratively using List.iter
and
Map.iter
.
for nested in all do for e in nested do printfn $"{e.Key} {e.Value}"
Imperatively, we loop over the list using two for loops.
λ dotnet fsi main.fsx 1 map [(bananas, 3); (oranges, 2)] 2 map [(kiwis, 5); (plums, 4)] ------------------- 1 map [(bananas, 3); (oranges, 2)] 2 map [(kiwis, 5); (plums, 4)]
In this article we have worked with maps in F#.