# F# Map

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.

main.fsx
```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.

main.fsx
```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.

main.fsx
```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`.

main.fsx
```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.

main.fsx
```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")]
```

With `Add`, we add a new element to the map.

main.fsx
```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`.

main.fsx
```type User = {
Name: string
Occupation: string
}

let users =
Map.empty.

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.

main.fsx
```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)]
```