Diccionarios

Un Map es un diccionario, de modo tal que se accede a los datos a través de una llave.

let m1 = Map [3, "Apples" ; 2, "Bananas"]

printfn "%A" m1 
printfn "%A" m1[3] 

map [(2, "Bananas"); (3, "Apples")]
"Apples"
printfn "%A" m1.[5]
System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary.


   at Microsoft.FSharp.Collections.MapTreeModule.throwKeyNotFound[a]() in D:\a\_work\1\s\src\FSharp.Core\map.fs:line 187


   at Microsoft.FSharp.Collections.MapTreeModule.find[TKey,TValue](IComparer`1 comparer, TKey k, MapTree`2 m) in D:\a\_work\1\s\src\FSharp.Core\map.fs:line 196


   at Microsoft.FSharp.Collections.FSharpMap`2.get_Item(TKey key) in D:\a\_work\1\s\src\FSharp.Core\map.fs:line 777


   at <StartupCode$FSI_0011>.$FSI_0011.main@()


   at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)


   at System.Reflection.MethodInvoker.Invoke(Object obj, IntPtr* args, BindingFlags invokeAttr)

A diferencia de las listas, es posible crear nuevos diccionarios usando funciones para agregar o cambiar ciertos valores:

let m2 = m1.Add(4,"Oranges")
printfn "%A" m2

map [(2, "Bananas"); (3, "Apples"); (4, "Oranges")]
let m3 = Map.add 2 "Peaches" m2 
printfn "%A" m2
printfn "%A" m3

map [(2, "Bananas"); (3, "Apples"); (4, "Oranges")]
map [(2, "Peaches"); (3, "Apples"); (4, "Oranges")]

Veamos algunas funciones similares con el ejemplo de los ⭐️⭐️⭐️:

type Position = GoalKeeper | Defender | Midfielder | Forward 

type Player =
    {
        Name : string
        Team: string 
        Position: Position 
        Age: uint8 
    }
let champions2022 = Map [// Los 3 arqueros de Argentina en Qatar 2022
     23, { Name = "Emiliano Martínez" ;  Team = "Aston Villa"; Position = GoalKeeper; Age = 30uy};
     12, { Name = "Gerónimo Rulli" ;  Team = "Villarreal"; Position = GoalKeeper; Age = 30uy};
     1, { Name = "Franco Armani" ;  Team = "River"; Position = GoalKeeper; Age = 36uy};
    // Los 9 defensores de Argentina en Qatar 2022
     26, { Name = "Nahuel Molina" ;  Team = "Atlético de Madrid"; Position = Defender; Age = 24uy};
     4, { Name = "Gonzalo Montiel" ;  Team = "Sevilla"; Position = Defender; Age = 25uy};
     13, { Name = "Cristian Romero" ;  Team = "Tottenham"; Position = Defender; Age = 24uy};
     6, { Name = "Germán Pezzella" ;  Team = "Betis"; Position = Defender; Age = 31uy};
     19, { Name = "Nicolás Otamendi" ;  Team = "Benfica"; Position = Defender; Age = 34uy};
     25, { Name = "Lisandro Martínez" ;  Team = "Manchester United"; Position = Defender; Age = 24uy};
     8, { Name = "Marcos Acuña" ;  Team = "Sevilla"; Position = Defender; Age = 31uy};
     3, { Name = "Nicolás Tagliafico" ;  Team = "Olympique de Lyon"; Position = Defender; Age = 30uy};
     2, { Name = "Juan Foyth" ;  Team = "Villarreal"; Position = Defender; Age = 24uy};
    // Los 8 mediocampistas de Argentina en Qatar 2022
     7, { Name = "Rodrigo De Paul" ;  Team = "Atlético de Madrid"; Position = Midfielder; Age = 28uy};
     5, { Name = "Leandro Paredes" ;  Team = "Juventus"; Position = Midfielder; Age = 28uy};
     20, { Name = "Alexis Mac Allister" ;  Team = "Brighton"; Position = Midfielder; Age = 23uy};
     18, { Name = "Guido Rodríguez" ;  Team = "Betis"; Position = Midfielder; Age = 28uy};
     17, { Name = "Alejandro Gómez" ;  Team = "Sevilla"; Position = Midfielder; Age = 34uy};
     24, { Name = "Enzo Fernández" ;  Team = "Benfica"; Position = Midfielder; Age = 21uy};
     14, { Name = "Exequiel Palacios" ;  Team = "Bayer Leverkusen"; Position = Midfielder; Age = 24uy};
     16, { Name = "Thiago Almada" ;  Team = "Atlanta United"; Position = Midfielder; Age = 21uy};
    // Los 6 delanteros de Argentina en Qatar 2022
     11, { Name = "Ángel Di María" ;  Team = "Juventus"; Position = Forward; Age = 34uy};
     22, { Name = "Lautaro Martínez" ;  Team = "Inter"; Position = Forward; Age = 25uy};
     9, { Name = "Julián Álvarez" ;  Team = "Manchester City"; Position = Forward; Age = 22uy};
     21, { Name = "Paulo Dybala" ;  Team = "Roma"; Position = Forward; Age = 29uy};
     15, { Name = "Ángel Correa" ;  Team = "Atlético Madrid"; Position = Forward; Age = 27uy};
     10, { Name = "Lionel Messi" ;  Team = "París Saint-Germain"; Position = Forward; Age = 35uy};
]
let toStringPlayer number player = 
    $"{number}: {player.Name} ({player.Age}), {player.Position}, juega en {player.Team}"


let prettyPrintMap m = 
    m
    |> Map.iter (fun n p -> printfn "%s" (toStringPlayer n p))  

prettyPrintMap champions2022       
1: Franco Armani (36), GoalKeeper, juega en River
2: Juan Foyth (24), Defender, juega en Villarreal
3: Nicolás Tagliafico (30), Defender, juega en Olympique de Lyon
4: Gonzalo Montiel (25), Defender, juega en Sevilla
5: Leandro Paredes (28), Midfielder, juega en Juventus
6: Germán Pezzella (31), Defender, juega en Betis
7: Rodrigo De Paul (28), Midfielder, juega en Atlético de Madrid
8: Marcos Acuña (31), Defender, juega en Sevilla
9: Julián Álvarez (22), Forward, juega en Manchester City
10: Lionel Messi (35), Forward, juega en París Saint-Germain
11: Ángel Di María (34), Forward, juega en Juventus
12: Gerónimo Rulli (30), GoalKeeper, juega en Villarreal
13: Cristian Romero (24), Defender, juega en Tottenham
14: Exequiel Palacios (24), Midfielder, juega en Bayer Leverkusen
15: Ángel Correa (27), Forward, juega en Atlético Madrid
16: Thiago Almada (21), Midfielder, juega en Atlanta United
17: Alejandro Gómez (34), Midfielder, juega en Sevilla
18: Guido Rodríguez (28), Midfielder, juega en Betis
19: Nicolás Otamendi (34), Defender, juega en Benfica
20: Alexis Mac Allister (23), Midfielder, juega en Brighton
21: Paulo Dybala (29), Forward, juega en Roma
22: Lautaro Martínez (25), Forward, juega en Inter
23: Emiliano Martínez (30), GoalKeeper, juega en Aston Villa
24: Enzo Fernández (21), Midfielder, juega en Benfica
25: Lisandro Martínez (24), Defender, juega en Manchester United
26: Nahuel Molina (24), Defender, juega en Atlético de Madrid
champions2022 
|> Map.toList 
|> List.sortBy (fun (n,p) -> n)
|> Map.ofList
|> prettyPrintMap
1: Franco Armani (36), GoalKeeper, juega en River
2: Juan Foyth (24), Defender, juega en Villarreal
3: Nicolás Tagliafico (30), Defender, juega en Olympique de Lyon
4: Gonzalo Montiel (25), Defender, juega en Sevilla
5: Leandro Paredes (28), Midfielder, juega en Juventus
6: Germán Pezzella (31), Defender, juega en Betis
7: Rodrigo De Paul (28), Midfielder, juega en Atlético de Madrid
8: Marcos Acuña (31), Defender, juega en Sevilla
9: Julián Álvarez (22), Forward, juega en Manchester City
10: Lionel Messi (35), Forward, juega en París Saint-Germain
11: Ángel Di María (34), Forward, juega en Juventus
12: Gerónimo Rulli (30), GoalKeeper, juega en Villarreal
13: Cristian Romero (24), Defender, juega en Tottenham
14: Exequiel Palacios (24), Midfielder, juega en Bayer Leverkusen
15: Ángel Correa (27), Forward, juega en Atlético Madrid
16: Thiago Almada (21), Midfielder, juega en Atlanta United
17: Alejandro Gómez (34), Midfielder, juega en Sevilla
18: Guido Rodríguez (28), Midfielder, juega en Betis
19: Nicolás Otamendi (34), Defender, juega en Benfica
20: Alexis Mac Allister (23), Midfielder, juega en Brighton
21: Paulo Dybala (29), Forward, juega en Roma
22: Lautaro Martínez (25), Forward, juega en Inter
23: Emiliano Martínez (30), GoalKeeper, juega en Aston Villa
24: Enzo Fernández (21), Midfielder, juega en Benfica
25: Lisandro Martínez (24), Defender, juega en Manchester United
26: Nahuel Molina (24), Defender, juega en Atlético de Madrid

Quizás uno no necesita imprimir todos los datos de cada jugador:

champions2022 
|> Map.map (fun _ p -> $"{p.Name} tiene {p.Age} años")
|> Map.iter (fun _ s -> printfn "%s" s)
Franco Armani tiene 36 años
Juan Foyth tiene 24 años
Nicolás Tagliafico tiene 30 años
Gonzalo Montiel tiene 25 años
Leandro Paredes tiene 28 años
Germán Pezzella tiene 31 años
Rodrigo De Paul tiene 28 años
Marcos Acuña tiene 31 años
Julián Álvarez tiene 22 años
Lionel Messi tiene 35 años
Ángel Di María tiene 34 años
Gerónimo Rulli tiene 30 años
Cristian Romero tiene 24 años
Exequiel Palacios tiene 24 años
Ángel Correa tiene 27 años
Thiago Almada tiene 21 años
Alejandro Gómez tiene 34 años
Guido Rodríguez tiene 28 años
Nicolás Otamendi tiene 34 años
Alexis Mac Allister tiene 23 años
Paulo Dybala tiene 29 años
Lautaro Martínez tiene 25 años
Emiliano Martínez tiene 30 años
Enzo Fernández tiene 21 años
Lisandro Martínez tiene 24 años
Nahuel Molina tiene 24 años

Se puede buscar algún elemento del diccionario a través de la llave:

champions2022
|> Map.find 22

{ Name = "Lautaro Martínez"\n Team = "Inter"\n Position = Forward\n Age = 25uy }
NameLautaro Martínez
TeamInter
Position
Forward
Age
25
champions2022
|> Map.find 31
System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary.


   at Microsoft.FSharp.Collections.MapTreeModule.throwKeyNotFound[a]() in D:\a\_work\1\s\src\FSharp.Core\map.fs:line 187


   at Microsoft.FSharp.Collections.MapTreeModule.find[TKey,TValue](IComparer`1 comparer, TKey k, MapTree`2 m) in D:\a\_work\1\s\src\FSharp.Core\map.fs:line 196


   at Microsoft.FSharp.Collections.MapModule.Find[TKey,T](TKey key, FSharpMap`2 table) in D:\a\_work\1\s\src\FSharp.Core\map.fs:line 1148


   at <StartupCode$FSI_0039>.$FSI_0039.main@()


   at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)


   at System.Reflection.MethodInvoker.Invoke(Object obj, IntPtr* args, BindingFlags invokeAttr)

Nótese que Map.find devuelve obviamente el único elemento que encuentra. Si uno quiere todos los elementos que comparten una cierta característica, usamos Map.filter

champions2022
|> Map.filter (fun _ p -> p.Age = 21uy)
keyvalue
16
{ Name = "Thiago Almada"\n Team = "Atlanta United"\n Position = Midfielder\n Age = 21uy }
NameThiago Almada
TeamAtlanta United
Position
Midfielder
Age
21
24
{ Name = "Enzo Fernández"\n Team = "Benfica"\n Position = Midfielder\n Age = 21uy }
NameEnzo Fernández
TeamBenfica
Position
Midfielder
Age
21
let arqueros = 
    champions2022
    |> Map.filter (fun _ p -> p.Position = GoalKeeper)

prettyPrintMap arqueros    
1: Franco Armani (36), GoalKeeper, juega en River
12: Gerónimo Rulli (30), GoalKeeper, juega en Villarreal
23: Emiliano Martínez (30), GoalKeeper, juega en Aston Villa

Podemos usar otros métodos para procesar los datos del diccionario, pero puede ser necesario convertirlas a una la lista con Map.ofList:

champions2022
|> Map.toList 
|> List.averageBy (fun (_,p) -> float p.Age)
27.76923076923077

La función Map.partition nos permite agrupar los elementos en dos diccionarios con características disjuntas:

let menoresde30, mayoresde30 = 
    champions2022
    |> Map.map (fun _ p -> (p.Name,p.Age))
    |> Map.partition (fun _ (name,age) -> age < 30uy)

printfn $"Los menores de 30 son {menoresde30.Count}"
printfn $"Los mayores de 30 son {mayoresde30.Count}"
Los menores de 30 son 16
Los mayores de 30 son 10

Finalmente, algunas funciones nos permiten evaluar una determinada característica de un diccionario:

champions2022
|> Map.forall (fun _ p -> p.Age < 30uy)
False
Map.keys champions2022
[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 ... (6 more) ]
champions2022
|> Map.toList 
|> List.map (fun (k,_)-> k)
[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 ... (more) ]
Map.values champions2022
indexvalue
0
{ Name = "Franco Armani"\n Team = "River"\n Position = GoalKeeper\n Age = 36uy }
NameFranco Armani
TeamRiver
Position
GoalKeeper
Age
36
1
{ Name = "Juan Foyth"\n Team = "Villarreal"\n Position = Defender\n Age = 24uy }
NameJuan Foyth
TeamVillarreal
Position
Defender
Age
24
2
{ Name = "Nicolás Tagliafico"\n Team = "Olympique de Lyon"\n Position = Defender\n Age = 30uy }
NameNicolás Tagliafico
TeamOlympique de Lyon
Position
Defender
Age
30
3
{ Name = "Gonzalo Montiel"\n Team = "Sevilla"\n Position = Defender\n Age = 25uy }
NameGonzalo Montiel
TeamSevilla
Position
Defender
Age
25
4
{ Name = "Leandro Paredes"\n Team = "Juventus"\n Position = Midfielder\n Age = 28uy }
NameLeandro Paredes
TeamJuventus
Position
Midfielder
Age
28
5
{ Name = "Germán Pezzella"\n Team = "Betis"\n Position = Defender\n Age = 31uy }
NameGermán Pezzella
TeamBetis
Position
Defender
Age
31
6
{ Name = "Rodrigo De Paul"\n Team = "Atlético de Madrid"\n Position = Midfielder\n Age = 28uy }
NameRodrigo De Paul
TeamAtlético de Madrid
Position
Midfielder
Age
28
7
{ Name = "Marcos Acuña"\n Team = "Sevilla"\n Position = Defender\n Age = 31uy }
NameMarcos Acuña
TeamSevilla
Position
Defender
Age
31
8
{ Name = "Julián Álvarez"\n Team = "Manchester City"\n Position = Forward\n Age = 22uy }
NameJulián Álvarez
TeamManchester City
Position
Forward
Age
22
9
{ Name = "Lionel Messi"\n Team = "París Saint-Germain"\n Position = Forward\n Age = 35uy }
NameLionel Messi
TeamParís Saint-Germain
Position
Forward
Age
35
10
{ Name = "Ángel Di María"\n Team = "Juventus"\n Position = Forward\n Age = 34uy }
NameÁngel Di María
TeamJuventus
Position
Forward
Age
34
11
{ Name = "Gerónimo Rulli"\n Team = "Villarreal"\n Position = GoalKeeper\n Age = 30uy }
NameGerónimo Rulli
TeamVillarreal
Position
GoalKeeper
Age
30
12
{ Name = "Cristian Romero"\n Team = "Tottenham"\n Position = Defender\n Age = 24uy }
NameCristian Romero
TeamTottenham
Position
Defender
Age
24
13
{ Name = "Exequiel Palacios"\n Team = "Bayer Leverkusen"\n Position = Midfielder\n Age = 24uy }
NameExequiel Palacios
TeamBayer Leverkusen
Position
Midfielder
Age
24
14
{ Name = "Ángel Correa"\n Team = "Atlético Madrid"\n Position = Forward\n Age = 27uy }
NameÁngel Correa
TeamAtlético Madrid
Position
Forward
Age
27
15
{ Name = "Thiago Almada"\n Team = "Atlanta United"\n Position = Midfielder\n Age = 21uy }
NameThiago Almada
TeamAtlanta United
Position
Midfielder
Age
21
16
{ Name = "Alejandro Gómez"\n Team = "Sevilla"\n Position = Midfielder\n Age = 34uy }
NameAlejandro Gómez
TeamSevilla
Position
Midfielder
Age
34
17
{ Name = "Guido Rodríguez"\n Team = "Betis"\n Position = Midfielder\n Age = 28uy }
NameGuido Rodríguez
TeamBetis
Position
Midfielder
Age
28
18
{ Name = "Nicolás Otamendi"\n Team = "Benfica"\n Position = Defender\n Age = 34uy }
NameNicolás Otamendi
TeamBenfica
Position
Defender
Age
34
19
{ Name = "Alexis Mac Allister"\n Team = "Brighton"\n Position = Midfielder\n Age = 23uy }
NameAlexis Mac Allister
TeamBrighton
Position
Midfielder
Age
23
... (more)
champions2022
|> Map.toList 
|> List.map (fun (_,v)-> v)
indexvalue
0
{ Name = "Franco Armani"\n Team = "River"\n Position = GoalKeeper\n Age = 36uy }
NameFranco Armani
TeamRiver
Position
GoalKeeper
Age
36
1
{ Name = "Juan Foyth"\n Team = "Villarreal"\n Position = Defender\n Age = 24uy }
NameJuan Foyth
TeamVillarreal
Position
Defender
Age
24
2
{ Name = "Nicolás Tagliafico"\n Team = "Olympique de Lyon"\n Position = Defender\n Age = 30uy }
NameNicolás Tagliafico
TeamOlympique de Lyon
Position
Defender
Age
30
3
{ Name = "Gonzalo Montiel"\n Team = "Sevilla"\n Position = Defender\n Age = 25uy }
NameGonzalo Montiel
TeamSevilla
Position
Defender
Age
25
4
{ Name = "Leandro Paredes"\n Team = "Juventus"\n Position = Midfielder\n Age = 28uy }
NameLeandro Paredes
TeamJuventus
Position
Midfielder
Age
28
5
{ Name = "Germán Pezzella"\n Team = "Betis"\n Position = Defender\n Age = 31uy }
NameGermán Pezzella
TeamBetis
Position
Defender
Age
31
6
{ Name = "Rodrigo De Paul"\n Team = "Atlético de Madrid"\n Position = Midfielder\n Age = 28uy }
NameRodrigo De Paul
TeamAtlético de Madrid
Position
Midfielder
Age
28
7
{ Name = "Marcos Acuña"\n Team = "Sevilla"\n Position = Defender\n Age = 31uy }
NameMarcos Acuña
TeamSevilla
Position
Defender
Age
31
8
{ Name = "Julián Álvarez"\n Team = "Manchester City"\n Position = Forward\n Age = 22uy }
NameJulián Álvarez
TeamManchester City
Position
Forward
Age
22
9
{ Name = "Lionel Messi"\n Team = "París Saint-Germain"\n Position = Forward\n Age = 35uy }
NameLionel Messi
TeamParís Saint-Germain
Position
Forward
Age
35
10
{ Name = "Ángel Di María"\n Team = "Juventus"\n Position = Forward\n Age = 34uy }
NameÁngel Di María
TeamJuventus
Position
Forward
Age
34
11
{ Name = "Gerónimo Rulli"\n Team = "Villarreal"\n Position = GoalKeeper\n Age = 30uy }
NameGerónimo Rulli
TeamVillarreal
Position
GoalKeeper
Age
30
12
{ Name = "Cristian Romero"\n Team = "Tottenham"\n Position = Defender\n Age = 24uy }
NameCristian Romero
TeamTottenham
Position
Defender
Age
24
13
{ Name = "Exequiel Palacios"\n Team = "Bayer Leverkusen"\n Position = Midfielder\n Age = 24uy }
NameExequiel Palacios
TeamBayer Leverkusen
Position
Midfielder
Age
24
14
{ Name = "Ángel Correa"\n Team = "Atlético Madrid"\n Position = Forward\n Age = 27uy }
NameÁngel Correa
TeamAtlético Madrid
Position
Forward
Age
27
15
{ Name = "Thiago Almada"\n Team = "Atlanta United"\n Position = Midfielder\n Age = 21uy }
NameThiago Almada
TeamAtlanta United
Position
Midfielder
Age
21
16
{ Name = "Alejandro Gómez"\n Team = "Sevilla"\n Position = Midfielder\n Age = 34uy }
NameAlejandro Gómez
TeamSevilla
Position
Midfielder
Age
34
17
{ Name = "Guido Rodríguez"\n Team = "Betis"\n Position = Midfielder\n Age = 28uy }
NameGuido Rodríguez
TeamBetis
Position
Midfielder
Age
28
18
{ Name = "Nicolás Otamendi"\n Team = "Benfica"\n Position = Defender\n Age = 34uy }
NameNicolás Otamendi
TeamBenfica
Position
Defender
Age
34
19
{ Name = "Alexis Mac Allister"\n Team = "Brighton"\n Position = Midfielder\n Age = 23uy }
NameAlexis Mac Allister
TeamBrighton
Position
Midfielder
Age
23
... (more)

results matching ""

    No results matching ""