Más sobre Colecciones
Hasta ahora hemos visto el tipo de colección list
, que es esencialmente una lista simplemente enlazada. La definición de list
es similar a la que propusimos con MyList
, pero
- es general para cualquier tipo de dato
- utiliza símbolos adecuados en lugar de etiquetas
type List<'T> =
| ([])
| ( :: ) of Head: 'T * Tail: 'T list
Como una lista es una unión discriminada, puede usarse tal cual cualquiera de ellas. Por ejemplo, se puede escribir una función para imprimir los elementos de una lista:
// loop through a list and print the values
let rec loopAndPrint aList =
match aList with
// empty list means we're done.
| [] ->
printfn "empty"
// binding to head::tail.
| x::xs ->
printfn "element=%A," x
// do all over again with the
// rest of the list
loopAndPrint xs
loopAndPrint []
let l = [1;2;3]
l |> loopAndPrint
element=1,
element=2,
element=3,
empty
Se puede acceder a distintos elementos de la lista a través de índices, aunque su uso no es generalizado. Si se utilizan las funciones Head
y Tail
para encontrar el primer elemento y el resto de la lista:
printfn "%A" l.Head
printfn "%A" (l |> List.head)
printfn "%A" l.Tail
printfn "%A" (l |> List.tail)
Acá podemos ver dos variantes de estas funciones:
- Aquellas del tipo
List.
que provienen del módulo de listas de F#,
- Métodos que un tipo de dato
list
.
En el caso de los métodos, vemos cómo F# provee también características asociadas a la programación orientada a objeto.
Hay que prestar atención a que una lista pueda ser vacía, porque en ese caso estos métodos devuelven una excepción:
System.InvalidOperationException: The input list was empty.
at Microsoft.FSharp.Collections.FSharpList`1.get_Head() in D:\a\_work\1\s\src\FSharp.Core\prim-types.fs:line 4072
at <StartupCode$FSI_0010>.$FSI_0010.main@()
at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
at System.Reflection.MethodInvoker.Invoke(Object obj, IntPtr* args, BindingFlags invokeAttr)
System.InvalidOperationException: The input list was empty.
at Microsoft.FSharp.Collections.FSharpList`1.get_Tail() in D:\a\_work\1\s\src\FSharp.Core\prim-types.fs:line 4077
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)
Usando la notación de listas, se pueden crear así:
let l = 3 :: [6;7]
printfn "%A" l
o concatenando dos listas:
let l2 = l @ [8;9]
printfn "%A" l2
Procesando listas
Como venimos insistiendo, la idea de las colecciones es poder procesarlas a través de un función, o una serie concatenada de funciones (usando piping) de forma tal de poder obtener el resultado adecuado.
Vimos que las funciones sobre colecciones se pueden clasificar de acuerdo al tipo de inputs y outputs de cada una de ellas. Detallando esta idea, en la siguiente imagen se ven algunos ejemplos de ellas, y qué tipos de inputs y outputs poseen (del libro Stylish F#, de Kit Easton):
La mayoría de estas funciones reciben como argumento una función y una lista, y devuelven una lista nueva con la transformación correspondiente. La función en general suele escribirse como una función anónima:
fun arguments -> expression
también conocidas como funciones lambda.
Trabajemos con un ejemplo para ir incorporando este concepto. Para ello, usaremos un par de tipos de datos Position
y Player
que describen algunas características de un jugador de fútbol:
type Position = GoalKeeper | Defender | Midfielder | Forward
type Player =
{
Number: int
Name : string
Team: string
Position: Position
Age: uint8
}
Obviamente, el ejemplo seguirá usando los siguientes ⭐️⭐️⭐️ :
let champions2022 = [
// Los 3 arqueros de Argentina en Qatar 2022
{Number = 23; Name = "Emiliano Martínez" ; Team = "Aston Villa"; Position = GoalKeeper; Age = 30uy};
{Number = 12; Name = "Gerónimo Rulli" ; Team = "Villarreal"; Position = GoalKeeper; Age = 30uy};
{Number = 1; Name = "Franco Armani" ; Team = "River"; Position = GoalKeeper; Age = 36uy};
// Los 9 defensores de Argentina en Qatar 2022
{Number = 26; Name = "Nahuel Molina" ; Team = "Atlético de Madrid"; Position = Defender; Age = 24uy};
{Number = 4; Name = "Gonzalo Montiel" ; Team = "Sevilla"; Position = Defender; Age = 25uy};
{Number = 13; Name = "Cristian Romero" ; Team = "Tottenham"; Position = Defender; Age = 24uy};
{Number = 6; Name = "Germán Pezzella" ; Team = "Betis"; Position = Defender; Age = 31uy};
{Number = 19; Name = "Nicolás Otamendi" ; Team = "Benfica"; Position = Defender; Age = 34uy};
{Number = 25; Name = "Lisandro Martínez" ; Team = "Manchester United"; Position = Defender; Age = 24uy};
{Number = 8; Name = "Marcos Acuña" ; Team = "Sevilla"; Position = Defender; Age = 31uy};
{Number = 3; Name = "Nicolás Tagliafico" ; Team = "Olympique de Lyon"; Position = Defender; Age = 30uy};
{Number = 2; Name = "Juan Foyth" ; Team = "Villarreal"; Position = Defender; Age = 24uy};
// Los 8 mediocampistas de Argentina en Qatar 2022
{Number = 7; Name = "Rodrigo De Paul" ; Team = "Atlético de Madrid"; Position = Midfielder; Age = 28uy};
{Number = 5; Name = "Leandro Paredes" ; Team = "Juventus"; Position = Midfielder; Age = 28uy};
{Number = 20; Name = "Alexis Mac Allister" ; Team = "Brighton"; Position = Midfielder; Age = 23uy};
{Number = 18; Name = "Guido Rodríguez" ; Team = "Betis"; Position = Midfielder; Age = 28uy};
{Number = 17; Name = "Alejandro Gómez" ; Team = "Sevilla"; Position = Midfielder; Age = 34uy};
{Number = 24; Name = "Enzo Fernández" ; Team = "Benfica"; Position = Midfielder; Age = 21uy};
{Number = 14; Name = "Exequiel Palacios" ; Team = "Bayer Leverkusen"; Position = Midfielder; Age = 24uy};
{Number = 16; Name = "Thiago Almada" ; Team = "Atlanta United"; Position = Midfielder; Age = 21uy};
// Los 6 delanteros de Argentina en Qatar 2022
{Number = 11; Name = "Ángel Di María" ; Team = "Juventus"; Position = Forward; Age = 34uy};
{Number = 22; Name = "Lautaro Martínez" ; Team = "Inter"; Position = Forward; Age = 25uy};
{Number = 9; Name = "Julián Álvarez" ; Team = "Manchester City"; Position = Forward; Age = 22uy};
{Number = 21; Name = "Paulo Dybala" ; Team = "Roma"; Position = Forward; Age = 29uy};
{Number = 15; Name = "Ángel Correa" ; Team = "Atlético Madrid"; Position = Forward; Age = 27uy};
{Number = 10; Name = "Lionel Messi" ; Team = "París Saint-Germain"; Position = Forward; Age = 35uy};
]
Definamos una función que nos permite recorrer la lista e imprimirla. Para eso usamos List.iter
que, justamente, itera la lista y devuelve unit
:
let almostPrettyPrintList l =
l
|> List.iter (fun elem -> printfn "%A" elem)
champions2022
|> almostPrettyPrintList
{ Number = 23
Name = "Emiliano Martínez"
Team = "Aston Villa"
Position = GoalKeeper
Age = 30uy }
{ Number = 12
Name = "Gerónimo Rulli"
Team = "Villarreal"
Position = GoalKeeper
Age = 30uy }
{ Number = 1
Name = "Franco Armani"
Team = "River"
Position = GoalKeeper
Age = 36uy }
{ Number = 26
Name = "Nahuel Molina"
Team = "Atlético de Madrid"
Position = Defender
Age = 24uy }
{ Number = 4
Name = "Gonzalo Montiel"
Team = "Sevilla"
Position = Defender
Age = 25uy }
{ Number = 13
Name = "Cristian Romero"
Team = "Tottenham"
Position = Defender
Age = 24uy }
{ Number = 6
Name = "Germán Pezzella"
Team = "Betis"
Position = Defender
Age = 31uy }
{ Number = 19
Name = "Nicolás Otamendi"
Team = "Benfica"
Position = Defender
Age = 34uy }
{ Number = 25
Name = "Lisandro Martínez"
Team = "Manchester United"
Position = Defender
Age = 24uy }
{ Number = 8
Name = "Marcos Acuña"
Team = "Sevilla"
Position = Defender
Age = 31uy }
{ Number = 3
Name = "Nicolás Tagliafico"
Team = "Olympique de Lyon"
Position = Defender
Age = 30uy }
{ Number = 2
Name = "Juan Foyth"
Team = "Villarreal"
Position = Defender
Age = 24uy }
{ Number = 7
Name = "Rodrigo De Paul"
Team = "Atlético de Madrid"
Position = Midfielder
Age = 28uy }
{ Number = 5
Name = "Leandro Paredes"
Team = "Juventus"
Position = Midfielder
Age = 28uy }
{ Number = 20
Name = "Alexis Mac Allister"
Team = "Brighton"
Position = Midfielder
Age = 23uy }
{ Number = 18
Name = "Guido Rodríguez"
Team = "Betis"
Position = Midfielder
Age = 28uy }
{ Number = 17
Name = "Alejandro Gómez"
Team = "Sevilla"
Position = Midfielder
Age = 34uy }
{ Number = 24
Name = "Enzo Fernández"
Team = "Benfica"
Position = Midfielder
Age = 21uy }
{ Number = 14
Name = "Exequiel Palacios"
Team = "Bayer Leverkusen"
Position = Midfielder
Age = 24uy }
{ Number = 16
Name = "Thiago Almada"
Team = "Atlanta United"
Position = Midfielder
Age = 21uy }
{ Number = 11
Name = "Ángel Di María"
Team = "Juventus"
Position = Forward
Age = 34uy }
{ Number = 22
Name = "Lautaro Martínez"
Team = "Inter"
Position = Forward
Age = 25uy }
{ Number = 9
Name = "Julián Álvarez"
Team = "Manchester City"
Position = Forward
Age = 22uy }
{ Number = 21
Name = "Paulo Dybala"
Team = "Roma"
Position = Forward
Age = 29uy }
{ Number = 15
Name = "Ángel Correa"
Team = "Atlético Madrid"
Position = Forward
Age = 27uy }
{ Number = 10
Name = "Lionel Messi"
Team = "París Saint-Germain"
Position = Forward
Age = 35uy }
Interpolated strings
No es muy compacto… Podemos crear una función que nos permita imprimir el dato de cada jugador en forma más elegante. Vamos a usar interpolated strings para hacerlo. Un interpolated string es una cadena de caracteres que comienza con el símbolo $
, y tiene el texto entre comillas dobles. En su interior se pueden usar los valores entre llaves {}
.
let saludo = "Hola"
printfn "{saludo} Mundo"
printfn $"{saludo} Mundo"
{saludo} Mundo
Hola Mundo
let toStringPlayer player =
$"{player.Number}: {player.Name} ({player.Age}), {player.Position}, juega en {player.Team}"
let prettyPrintList l =
l
|> List.iter (fun p -> printfn "%s" (toStringPlayer p))
prettyPrintList champions2022
23: Emiliano Martínez (30), GoalKeeper, juega en Aston Villa
12: Gerónimo Rulli (30), GoalKeeper, juega en Villarreal
1: Franco Armani (36), GoalKeeper, juega en River
26: Nahuel Molina (24), Defender, juega en Atlético de Madrid
4: Gonzalo Montiel (25), Defender, juega en Sevilla
13: Cristian Romero (24), Defender, juega en Tottenham
6: Germán Pezzella (31), Defender, juega en Betis
19: Nicolás Otamendi (34), Defender, juega en Benfica
25: Lisandro Martínez (24), Defender, juega en Manchester United
8: Marcos Acuña (31), Defender, juega en Sevilla
3: Nicolás Tagliafico (30), Defender, juega en Olympique de Lyon
2: Juan Foyth (24), Defender, juega en Villarreal
7: Rodrigo De Paul (28), Midfielder, juega en Atlético de Madrid
5: Leandro Paredes (28), Midfielder, juega en Juventus
20: Alexis Mac Allister (23), Midfielder, juega en Brighton
18: Guido Rodríguez (28), Midfielder, juega en Betis
17: Alejandro Gómez (34), Midfielder, juega en Sevilla
24: Enzo Fernández (21), Midfielder, juega en Benfica
14: Exequiel Palacios (24), Midfielder, juega en Bayer Leverkusen
16: Thiago Almada (21), Midfielder, juega en Atlanta United
11: Ángel Di María (34), Forward, juega en Juventus
22: Lautaro Martínez (25), Forward, juega en Inter
9: Julián Álvarez (22), Forward, juega en Manchester City
21: Paulo Dybala (29), Forward, juega en Roma
15: Ángel Correa (27), Forward, juega en Atlético Madrid
10: Lionel Messi (35), Forward, juega en París Saint-Germain
La lista se puede ordenar:
champions2022
|> List.sort
|> prettyPrintList
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
Vemos que la lista aparece ordenada primero por número. En este caso, List.sort
utiliza un comparador genérico para saber qué elemento está antes que otro. Sin embargo, la lista se puede ordenar de acuerdo a algún criterio usando List.sortBy
:
champions2022
|> List.sortBy (fun p -> p.Age)
|> prettyPrintList
24: Enzo Fernández (21), Midfielder, juega en Benfica
16: Thiago Almada (21), Midfielder, juega en Atlanta United
9: Julián Álvarez (22), Forward, juega en Manchester City
20: Alexis Mac Allister (23), Midfielder, juega en Brighton
26: Nahuel Molina (24), Defender, juega en Atlético de Madrid
13: Cristian Romero (24), Defender, juega en Tottenham
25: Lisandro Martínez (24), Defender, juega en Manchester United
2: Juan Foyth (24), Defender, juega en Villarreal
14: Exequiel Palacios (24), Midfielder, juega en Bayer Leverkusen
4: Gonzalo Montiel (25), Defender, juega en Sevilla
22: Lautaro Martínez (25), Forward, juega en Inter
15: Ángel Correa (27), Forward, juega en Atlético Madrid
7: Rodrigo De Paul (28), Midfielder, juega en Atlético de Madrid
5: Leandro Paredes (28), Midfielder, juega en Juventus
18: Guido Rodríguez (28), Midfielder, juega en Betis
21: Paulo Dybala (29), Forward, juega en Roma
23: Emiliano Martínez (30), GoalKeeper, juega en Aston Villa
12: Gerónimo Rulli (30), GoalKeeper, juega en Villarreal
3: Nicolás Tagliafico (30), Defender, juega en Olympique de Lyon
6: Germán Pezzella (31), Defender, juega en Betis
8: Marcos Acuña (31), Defender, juega en Sevilla
19: Nicolás Otamendi (34), Defender, juega en Benfica
17: Alejandro Gómez (34), Midfielder, juega en Sevilla
11: Ángel Di María (34), Forward, juega en Juventus
10: Lionel Messi (35), Forward, juega en París Saint-Germain
1: Franco Armani (36), GoalKeeper, juega en River
Quizás uno no necesita imprimir todos los datos de cada jugador:
champions2022
|> List.sortBy (fun p -> p.Age)
|> List.map (fun p -> $"{p.Name} tiene {p.Age} años")
|> List.iter (fun s -> printfn "%s" s)
Enzo Fernández tiene 21 años
Thiago Almada tiene 21 años
Julián Álvarez tiene 22 años
Alexis Mac Allister tiene 23 años
Nahuel Molina tiene 24 años
Cristian Romero tiene 24 años
Lisandro Martínez tiene 24 años
Juan Foyth tiene 24 años
Exequiel Palacios tiene 24 años
Gonzalo Montiel tiene 25 años
Lautaro Martínez tiene 25 años
Ángel Correa tiene 27 años
Rodrigo De Paul tiene 28 años
Leandro Paredes tiene 28 años
Guido Rodríguez tiene 28 años
Paulo Dybala tiene 29 años
Emiliano Martínez tiene 30 años
Gerónimo Rulli tiene 30 años
Nicolás Tagliafico tiene 30 años
Germán Pezzella tiene 31 años
Marcos Acuña tiene 31 años
Nicolás Otamendi tiene 34 años
Alejandro Gómez tiene 34 años
Ángel Di María tiene 34 años
Lionel Messi tiene 35 años
Franco Armani tiene 36 años
Se puede buscar algún elemento de la lista con alguna característica particular:
champions2022
|> List.find (fun p -> p.Age = 21uy)
{ Number = 24\n Name = "Enzo Fernández"\n Team = "Benfica"\n Position = Midfielder\n Age = 21uy }
|
Number | |
Name | Enzo Fernández |
Team | Benfica |
Position | Midfielder
|
Age | |
champions2022
|> List.sortBy (fun p -> p.Number)
|> List.find (fun p -> p.Age = 21uy)
{ Number = 16\n Name = "Thiago Almada"\n Team = "Atlanta United"\n Position = Midfielder\n Age = 21uy }
|
Number | |
Name | Thiago Almada |
Team | Atlanta United |
Position | Midfielder
|
Age | |
champions2022
|> List.find (fun p -> p.Age = 18uy)
System.Collections.Generic.KeyNotFoundException: An index satisfying the predicate was not found in the collection.
at Microsoft.FSharp.Collections.ListModule.Find[T](FSharpFunc`2 predicate, FSharpList`1 list) in D:\a\_work\1\s\src\FSharp.Core\list.fs:line 480
at <StartupCode$FSI_0084>.$FSI_0084.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 List.find
devuelve el primer elemento que encuentra. Si uno quiere todos los elementos que comparten una cierta característica, usamos List.filter
champions2022
|> List.filter (fun p -> p.Age = 21uy)
index | value |
---|
0 | { Number = 24\n Name = "Enzo Fernández"\n Team = "Benfica"\n Position = Midfielder\n Age = 21uy }
|
Number | | Name | Enzo Fernández | Team | Benfica | Position | Midfielder
| Age | |
|
1 | { Number = 16\n Name = "Thiago Almada"\n Team = "Atlanta United"\n Position = Midfielder\n Age = 21uy }
|
Number | | Name | Thiago Almada | Team | Atlanta United | Position | Midfielder
| Age | |
|
champions2022
|> List.filter (fun p -> p.Age > 25uy && p.Position = Defender)
index | value |
---|
0 | { Number = 6\n Name = "Germán Pezzella"\n Team = "Betis"\n Position = Defender\n Age = 31uy }
|
Number | | Name | Germán Pezzella | Team | Betis | Position | Defender
| Age | |
|
1 | { Number = 19\n Name = "Nicolás Otamendi"\n Team = "Benfica"\n Position = Defender\n Age = 34uy }
|
Number | | Name | Nicolás Otamendi | Team | Benfica | Position | Defender
| Age | |
|
2 | { Number = 8\n Name = "Marcos Acuña"\n Team = "Sevilla"\n Position = Defender\n Age = 31uy }
|
Number | | Name | Marcos Acuña | Team | Sevilla | Position | Defender
| Age | |
|
3 | { Number = 3\n Name = "Nicolás Tagliafico"\n Team = "Olympique de Lyon"\n Position = Defender\n Age = 30uy }
|
Number | | Name | Nicolás Tagliafico | Team | Olympique de Lyon | Position | Defender
| Age | |
|
let arqueros =
champions2022
|> List.filter (fun p -> p.Position = GoalKeeper)
prettyPrintList arqueros
23: Emiliano Martínez (30), GoalKeeper, juega en Aston Villa
12: Gerónimo Rulli (30), GoalKeeper, juega en Villarreal
1: Franco Armani (36), GoalKeeper, juega en River
Podemos usar otros métodos para procesar los datos de la lista:
champions2022
|> List.averageBy (fun p -> p.Age)
input.fsx (2,29)-(2,34) typecheck error The type 'uint8' does not support the operator 'DivideByInt'
Interesante, hay que convertir el dato a float
:
champions2022
|> List.averageBy (fun p -> float p.Age)
Hay funciones que permiten procesar la lista, recolectando datos que poseen características similares.
champions2022
|> List.groupBy (fun p -> p.Team)
index | value |
---|
0 | (Aston Villa, [{ Number = 23\n Name = "Emiliano Martínez"\n Team = "Aston Villa"\n Position = GoalKeeper\n Age = 30uy }])
|
Item1 | Aston Villa | Item2 | index | value |
---|
0 | { Number = 23\n Name = "Emiliano Martínez"\n Team = "Aston Villa"\n Position = GoalKeeper\n Age = 30uy }
|
Number | | Name | Emiliano Martínez | Team | Aston Villa | Position | GoalKeeper
| Age | |
|
|
|
1 | (Villarreal, [{ Number = 12\n Name = "Gerónimo Rulli"\n Team = "Villarreal"\n Position = GoalKeeper\n Age = 30uy }; { Number = 2\n Name = "Juan Foyth"\n Team = "Villarreal"\n Position = Defender\n Age = 24uy }])
|
Item1 | Villarreal | Item2 | index | value |
---|
0 | { Number = 12\n Name = "Gerónimo Rulli"\n Team = "Villarreal"\n Position = GoalKeeper\n Age = 30uy }
|
Number | | Name | Gerónimo Rulli | Team | Villarreal | Position | GoalKeeper
| Age | |
| 1 | { Number = 2\n Name = "Juan Foyth"\n Team = "Villarreal"\n Position = Defender\n Age = 24uy }
|
Number | | Name | Juan Foyth | Team | Villarreal | Position | Defender
| Age | |
|
|
|
2 | (River, [{ Number = 1\n Name = "Franco Armani"\n Team = "River"\n Position = GoalKeeper\n Age = 36uy }])
|
Item1 | River | Item2 | index | value |
---|
0 | { Number = 1\n Name = "Franco Armani"\n Team = "River"\n Position = GoalKeeper\n Age = 36uy }
|
Number | | Name | Franco Armani | Team | River | Position | GoalKeeper
| Age | |
|
|
|
3 | (Atlético de Madrid, [{ Number = 26\n Name = "Nahuel Molina"\n Team = "Atlético de Madrid"\n Position = Defender\n Age = 24uy }; { Number = 7\n Name = "Rodrigo De Paul"\n Team = "Atlético de Madrid"\n Position = Midfielder\n Age = 28uy }])
|
Item1 | Atlético de Madrid | Item2 | index | value |
---|
0 | { Number = 26\n Name = "Nahuel Molina"\n Team = "Atlético de Madrid"\n Position = Defender\n Age = 24uy }
|
Number | | Name | Nahuel Molina | Team | Atlético de Madrid | Position | Defender
| Age | |
| 1 | { Number = 7\n Name = "Rodrigo De Paul"\n Team = "Atlético de Madrid"\n Position = Midfielder\n Age = 28uy }
|
Number | | Name | Rodrigo De Paul | Team | Atlético de Madrid | Position | Midfielder
| Age | |
|
|
|
4 | (Sevilla, [{ Number = 4\n Name = "Gonzalo Montiel"\n Team = "Sevilla"\n Position = Defender\n Age = 25uy }; { Number = 8\n Name = "Marcos Acuña"\n Team = "Sevilla"\n Position = Defender\n Age = 31uy }; { Number = 17\n Name = "Alejandro Gómez"\n Team = "Sevilla"\n Position = Midfielder\n ...
|
Item1 | Sevilla | Item2 | index | value |
---|
0 | { Number = 4\n Name = "Gonzalo Montiel"\n Team = "Sevilla"\n Position = Defender\n Age = 25uy }
|
Number | | Name | Gonzalo Montiel | Team | Sevilla | Position | Defender
| Age | |
| 1 | { Number = 8\n Name = "Marcos Acuña"\n Team = "Sevilla"\n Position = Defender\n Age = 31uy }
|
Number | | Name | Marcos Acuña | Team | Sevilla | Position | Defender
| Age | |
| 2 | { Number = 17\n Name = "Alejandro Gómez"\n Team = "Sevilla"\n Position = Midfielder\n Age = 34uy }
|
Number | | Name | Alejandro Gómez | Team | Sevilla | Position | Midfielder
| Age | |
|
|
|
5 | (Tottenham, [{ Number = 13\n Name = "Cristian Romero"\n Team = "Tottenham"\n Position = Defender\n Age = 24uy }])
|
Item1 | Tottenham | Item2 | index | value |
---|
0 | { Number = 13\n Name = "Cristian Romero"\n Team = "Tottenham"\n Position = Defender\n Age = 24uy }
|
Number | | Name | Cristian Romero | Team | Tottenham | Position | Defender
| Age | |
|
|
|
6 | (Betis, [{ Number = 6\n Name = "Germán Pezzella"\n Team = "Betis"\n Position = Defender\n Age = 31uy }; { Number = 18\n Name = "Guido Rodríguez"\n Team = "Betis"\n Position = Midfielder\n Age = 28uy }])
|
Item1 | Betis | Item2 | index | value |
---|
0 | { Number = 6\n Name = "Germán Pezzella"\n Team = "Betis"\n Position = Defender\n Age = 31uy }
|
Number | | Name | Germán Pezzella | Team | Betis | Position | Defender
| Age | |
| 1 | { Number = 18\n Name = "Guido Rodríguez"\n Team = "Betis"\n Position = Midfielder\n Age = 28uy }
|
Number | | Name | Guido Rodríguez | Team | Betis | Position | Midfielder
| Age | |
|
|
|
7 | (Benfica, [{ Number = 19\n Name = "Nicolás Otamendi"\n Team = "Benfica"\n Position = Defender\n Age = 34uy }; { Number = 24\n Name = "Enzo Fernández"\n Team = "Benfica"\n Position = Midfielder\n Age = 21uy }])
|
Item1 | Benfica | Item2 | index | value |
---|
0 | { Number = 19\n Name = "Nicolás Otamendi"\n Team = "Benfica"\n Position = Defender\n Age = 34uy }
|
Number | | Name | Nicolás Otamendi | Team | Benfica | Position | Defender
| Age | |
| 1 | { Number = 24\n Name = "Enzo Fernández"\n Team = "Benfica"\n Position = Midfielder\n Age = 21uy }
|
Number | | Name | Enzo Fernández | Team | Benfica | Position | Midfielder
| Age | |
|
|
|
8 | (Manchester United, [{ Number = 25\n Name = "Lisandro Martínez"\n Team = "Manchester United"\n Position = Defender\n Age = 24uy }])
|
Item1 | Manchester United | Item2 | index | value |
---|
0 | { Number = 25\n Name = "Lisandro Martínez"\n Team = "Manchester United"\n Position = Defender\n Age = 24uy }
|
Number | | Name | Lisandro Martínez | Team | Manchester United | Position | Defender
| Age | |
|
|
|
9 | (Olympique de Lyon, [{ Number = 3\n Name = "Nicolás Tagliafico"\n Team = "Olympique de Lyon"\n Position = Defender\n Age = 30uy }])
|
Item1 | Olympique de Lyon | Item2 | index | value |
---|
0 | { Number = 3\n Name = "Nicolás Tagliafico"\n Team = "Olympique de Lyon"\n Position = Defender\n Age = 30uy }
|
Number | | Name | Nicolás Tagliafico | Team | Olympique de Lyon | Position | Defender
| Age | |
|
|
|
10 | (Juventus, [{ Number = 5\n Name = "Leandro Paredes"\n Team = "Juventus"\n Position = Midfielder\n Age = 28uy }; { Number = 11\n Name = "Ángel Di María"\n Team = "Juventus"\n Position = Forward\n Age = 34uy }])
|
Item1 | Juventus | Item2 | index | value |
---|
0 | { Number = 5\n Name = "Leandro Paredes"\n Team = "Juventus"\n Position = Midfielder\n Age = 28uy }
|
Number | | Name | Leandro Paredes | Team | Juventus | Position | Midfielder
| Age | |
| 1 | { Number = 11\n Name = "Ángel Di María"\n Team = "Juventus"\n Position = Forward\n Age = 34uy }
|
Number | | Name | Ángel Di María | Team | Juventus | Position | Forward
| Age | |
|
|
|
11 | (Brighton, [{ Number = 20\n Name = "Alexis Mac Allister"\n Team = "Brighton"\n Position = Midfielder\n Age = 23uy }])
|
Item1 | Brighton | Item2 | index | value |
---|
0 | { Number = 20\n Name = "Alexis Mac Allister"\n Team = "Brighton"\n Position = Midfielder\n Age = 23uy }
|
Number | | Name | Alexis Mac Allister | Team | Brighton | Position | Midfielder
| Age | |
|
|
|
12 | (Bayer Leverkusen, [{ Number = 14\n Name = "Exequiel Palacios"\n Team = "Bayer Leverkusen"\n Position = Midfielder\n Age = 24uy }])
|
Item1 | Bayer Leverkusen | Item2 | index | value |
---|
0 | { Number = 14\n Name = "Exequiel Palacios"\n Team = "Bayer Leverkusen"\n Position = Midfielder\n Age = 24uy }
|
Number | | Name | Exequiel Palacios | Team | Bayer Leverkusen | Position | Midfielder
| Age | |
|
|
|
13 | (Atlanta United, [{ Number = 16\n Name = "Thiago Almada"\n Team = "Atlanta United"\n Position = Midfielder\n Age = 21uy }])
|
Item1 | Atlanta United | Item2 | index | value |
---|
0 | { Number = 16\n Name = "Thiago Almada"\n Team = "Atlanta United"\n Position = Midfielder\n Age = 21uy }
|
Number | | Name | Thiago Almada | Team | Atlanta United | Position | Midfielder
| Age | |
|
|
|
14 | (Inter, [{ Number = 22\n Name = "Lautaro Martínez"\n Team = "Inter"\n Position = Forward\n Age = 25uy }])
|
Item1 | Inter | Item2 | index | value |
---|
0 | { Number = 22\n Name = "Lautaro Martínez"\n Team = "Inter"\n Position = Forward\n Age = 25uy }
|
Number | | Name | Lautaro Martínez | Team | Inter | Position | Forward
| Age | |
|
|
|
15 | (Manchester City, [{ Number = 9\n Name = "Julián Álvarez"\n Team = "Manchester City"\n Position = Forward\n Age = 22uy }])
|
Item1 | Manchester City | Item2 | index | value |
---|
0 | { Number = 9\n Name = "Julián Álvarez"\n Team = "Manchester City"\n Position = Forward\n Age = 22uy }
|
Number | | Name | Julián Álvarez | Team | Manchester City | Position | Forward
| Age | |
|
|
|
16 | (Roma, [{ Number = 21\n Name = "Paulo Dybala"\n Team = "Roma"\n Position = Forward\n Age = 29uy }])
|
Item1 | Roma | Item2 | index | value |
---|
0 | { Number = 21\n Name = "Paulo Dybala"\n Team = "Roma"\n Position = Forward\n Age = 29uy }
|
Number | | Name | Paulo Dybala | Team | Roma | Position | Forward
| Age | |
|
|
|
17 | (Atlético Madrid, [{ Number = 15\n Name = "Ángel Correa"\n Team = "Atlético Madrid"\n Position = Forward\n Age = 27uy }])
|
Item1 | Atlético Madrid | Item2 | index | value |
---|
0 | { Number = 15\n Name = "Ángel Correa"\n Team = "Atlético Madrid"\n Position = Forward\n Age = 27uy }
|
Number | | Name | Ángel Correa | Team | Atlético Madrid | Position | Forward
| Age | |
|
|
|
18 | (París Saint-Germain, [{ Number = 10\n Name = "Lionel Messi"\n Team = "París Saint-Germain"\n Position = Forward\n Age = 35uy }])
|
Item1 | París Saint-Germain | Item2 | index | value |
---|
0 | { Number = 10\n Name = "Lionel Messi"\n Team = "París Saint-Germain"\n Position = Forward\n Age = 35uy }
|
Number | | Name | Lionel Messi | Team | París Saint-Germain | Position | Forward
| Age | |
|
|
|
La función List.groupBy
no devuelve una lista de jugadores, sino una lista de pares ordenados (tuplas), donde el primer elemento sería la llave común del tipo de dato recolectado, y el segundo elemento es una lista de elementos que corresponden a esa llave:
champions2022
|> List.groupBy (fun p -> p.Team)
|> List.iter (fun (team,l) ->
printfn "%s" team
prettyPrintList l
)
Aston Villa
23: Emiliano Martínez (30), GoalKeeper, juega en Aston Villa
Villarreal
12: Gerónimo Rulli (30), GoalKeeper, juega en Villarreal
2: Juan Foyth (24), Defender, juega en Villarreal
River
1: Franco Armani (36), GoalKeeper, juega en River
Atlético de Madrid
26: Nahuel Molina (24), Defender, juega en Atlético de Madrid
7: Rodrigo De Paul (28), Midfielder, juega en Atlético de Madrid
Sevilla
4: Gonzalo Montiel (25), Defender, juega en Sevilla
8: Marcos Acuña (31), Defender, juega en Sevilla
17: Alejandro Gómez (34), Midfielder, juega en Sevilla
Tottenham
13: Cristian Romero (24), Defender, juega en Tottenham
Betis
6: Germán Pezzella (31), Defender, juega en Betis
18: Guido Rodríguez (28), Midfielder, juega en Betis
Benfica
19: Nicolás Otamendi (34), Defender, juega en Benfica
24: Enzo Fernández (21), Midfielder, juega en Benfica
Manchester United
25: Lisandro Martínez (24), Defender, juega en Manchester United
Olympique de Lyon
3: Nicolás Tagliafico (30), Defender, juega en Olympique de Lyon
Juventus
5: Leandro Paredes (28), Midfielder, juega en Juventus
11: Ángel Di María (34), Forward, juega en Juventus
Brighton
20: Alexis Mac Allister (23), Midfielder, juega en Brighton
Bayer Leverkusen
14: Exequiel Palacios (24), Midfielder, juega en Bayer Leverkusen
Atlanta United
16: Thiago Almada (21), Midfielder, juega en Atlanta United
Inter
22: Lautaro Martínez (25), Forward, juega en Inter
Manchester City
9: Julián Álvarez (22), Forward, juega en Manchester City
Roma
21: Paulo Dybala (29), Forward, juega en Roma
Atlético Madrid
15: Ángel Correa (27), Forward, juega en Atlético Madrid
París Saint-Germain
10: Lionel Messi (35), Forward, juega en París Saint-Germain
champions2022
|> List.groupBy (fun p -> p.Team)
|> List.iter (fun t ->
printfn "%s" (fst t)
prettyPrintList (snd t)
)
Aston Villa
23: Emiliano Martínez (30), GoalKeeper, juega en Aston Villa
Villarreal
12: Gerónimo Rulli (30), GoalKeeper, juega en Villarreal
2: Juan Foyth (24), Defender, juega en Villarreal
River
1: Franco Armani (36), GoalKeeper, juega en River
Atlético de Madrid
26: Nahuel Molina (24), Defender, juega en Atlético de Madrid
7: Rodrigo De Paul (28), Midfielder, juega en Atlético de Madrid
Sevilla
4: Gonzalo Montiel (25), Defender, juega en Sevilla
8: Marcos Acuña (31), Defender, juega en Sevilla
17: Alejandro Gómez (34), Midfielder, juega en Sevilla
Tottenham
13: Cristian Romero (24), Defender, juega en Tottenham
Betis
6: Germán Pezzella (31), Defender, juega en Betis
18: Guido Rodríguez (28), Midfielder, juega en Betis
Benfica
19: Nicolás Otamendi (34), Defender, juega en Benfica
24: Enzo Fernández (21), Midfielder, juega en Benfica
Manchester United
25: Lisandro Martínez (24), Defender, juega en Manchester United
Olympique de Lyon
3: Nicolás Tagliafico (30), Defender, juega en Olympique de Lyon
Juventus
5: Leandro Paredes (28), Midfielder, juega en Juventus
11: Ángel Di María (34), Forward, juega en Juventus
Brighton
20: Alexis Mac Allister (23), Midfielder, juega en Brighton
Bayer Leverkusen
14: Exequiel Palacios (24), Midfielder, juega en Bayer Leverkusen
Atlanta United
16: Thiago Almada (21), Midfielder, juega en Atlanta United
Inter
22: Lautaro Martínez (25), Forward, juega en Inter
Manchester City
9: Julián Álvarez (22), Forward, juega en Manchester City
Roma
21: Paulo Dybala (29), Forward, juega en Roma
Atlético Madrid
15: Ángel Correa (27), Forward, juega en Atlético Madrid
París Saint-Germain
10: Lionel Messi (35), Forward, juega en París Saint-Germain
Veamos cuántos jugadores aportó cada equipo:
champions2022
|> List.groupBy (fun p -> p.Team)
|> List.map (fun (t,l) -> (t, l |> List.length))
index | value |
---|
0 | (Aston Villa, 1)
|
1 | (Villarreal, 2)
|
2 | (River, 1)
|
3 | (Atlético de Madrid, 2)
|
Item1 | Atlético de Madrid | Item2 | |
|
4 | (Sevilla, 3)
|
5 | (Tottenham, 1)
|
6 | (Betis, 2)
|
7 | (Benfica, 2)
|
8 | (Manchester United, 1)
|
Item1 | Manchester United | Item2 | |
|
9 | (Olympique de Lyon, 1)
|
Item1 | Olympique de Lyon | Item2 | |
|
10 | (Juventus, 2)
|
11 | (Brighton, 1)
|
12 | (Bayer Leverkusen, 1)
|
Item1 | Bayer Leverkusen | Item2 | |
|
13 | (Atlanta United, 1)
|
14 | (Inter, 1)
|
15 | (Manchester City, 1)
|
Item1 | Manchester City | Item2 | |
|
16 | (Roma, 1)
|
17 | (Atlético Madrid, 1)
|
Item1 | Atlético Madrid | Item2 | |
|
18 | (París Saint-Germain, 1)
|
Item1 | París Saint-Germain | Item2 | |
|
Este último procedimiento se puede resumir con List.countBy
:
champions2022
|> List.countBy (fun p -> p.Team)
index | value |
---|
0 | (Aston Villa, 1)
|
1 | (Villarreal, 2)
|
2 | (River, 1)
|
3 | (Atlético de Madrid, 2)
|
Item1 | Atlético de Madrid | Item2 | |
|
4 | (Sevilla, 3)
|
5 | (Tottenham, 1)
|
6 | (Betis, 2)
|
7 | (Benfica, 2)
|
8 | (Manchester United, 1)
|
Item1 | Manchester United | Item2 | |
|
9 | (Olympique de Lyon, 1)
|
Item1 | Olympique de Lyon | Item2 | |
|
10 | (Juventus, 2)
|
11 | (Brighton, 1)
|
12 | (Bayer Leverkusen, 1)
|
Item1 | Bayer Leverkusen | Item2 | |
|
13 | (Atlanta United, 1)
|
14 | (Inter, 1)
|
15 | (Manchester City, 1)
|
Item1 | Manchester City | Item2 | |
|
16 | (Roma, 1)
|
17 | (Atlético Madrid, 1)
|
Item1 | Atlético Madrid | Item2 | |
|
18 | (París Saint-Germain, 1)
|
Item1 | París Saint-Germain | Item2 | |
|
Se puede construir un histograma de edades:
champions2022
|> List.groupBy (fun p -> p.Age/5uy * 5uy)
index | value |
---|
0 | (30, [{ Number = 23\n Name = "Emiliano Martínez"\n Team = "Aston Villa"\n Position = GoalKeeper\n Age = 30uy }; { Number = 12\n Name = "Gerónimo Rulli"\n Team = "Villarreal"\n Position = GoalKeeper\n Age = 30uy }; { Number = 6\n Name = "Germán Pezzella"\n Team = "Betis"\n Position = Defen...
|
Item1 | | Item2 | index | value |
---|
0 | { Number = 23\n Name = "Emiliano Martínez"\n Team = "Aston Villa"\n Position = GoalKeeper\n Age = 30uy }
|
Number | | Name | Emiliano Martínez | Team | Aston Villa | Position | GoalKeeper
| Age | |
| 1 | { Number = 12\n Name = "Gerónimo Rulli"\n Team = "Villarreal"\n Position = GoalKeeper\n Age = 30uy }
|
Number | | Name | Gerónimo Rulli | Team | Villarreal | Position | GoalKeeper
| Age | |
| 2 | { Number = 6\n Name = "Germán Pezzella"\n Team = "Betis"\n Position = Defender\n Age = 31uy }
|
Number | | Name | Germán Pezzella | Team | Betis | Position | Defender
| Age | |
| 3 | { Number = 19\n Name = "Nicolás Otamendi"\n Team = "Benfica"\n Position = Defender\n Age = 34uy }
|
Number | | Name | Nicolás Otamendi | Team | Benfica | Position | Defender
| Age | |
| 4 | { Number = 8\n Name = "Marcos Acuña"\n Team = "Sevilla"\n Position = Defender\n Age = 31uy }
|
Number | | Name | Marcos Acuña | Team | Sevilla | Position | Defender
| Age | |
| 5 | { Number = 3\n Name = "Nicolás Tagliafico"\n Team = "Olympique de Lyon"\n Position = Defender\n Age = 30uy }
|
Number | | Name | Nicolás Tagliafico | Team | Olympique de Lyon | Position | Defender
| Age | |
| 6 | { Number = 17\n Name = "Alejandro Gómez"\n Team = "Sevilla"\n Position = Midfielder\n Age = 34uy }
|
Number | | Name | Alejandro Gómez | Team | Sevilla | Position | Midfielder
| Age | |
| 7 | { Number = 11\n Name = "Ángel Di María"\n Team = "Juventus"\n Position = Forward\n Age = 34uy }
|
Number | | Name | Ángel Di María | Team | Juventus | Position | Forward
| Age | |
|
|
|
1 | (35, [{ Number = 1\n Name = "Franco Armani"\n Team = "River"\n Position = GoalKeeper\n Age = 36uy }; { Number = 10\n Name = "Lionel Messi"\n Team = "París Saint-Germain"\n Position = Forward\n Age = 35uy }])
|
Item1 | | Item2 | index | value |
---|
0 | { Number = 1\n Name = "Franco Armani"\n Team = "River"\n Position = GoalKeeper\n Age = 36uy }
|
Number | | Name | Franco Armani | Team | River | Position | GoalKeeper
| Age | |
| 1 | { Number = 10\n Name = "Lionel Messi"\n Team = "París Saint-Germain"\n Position = Forward\n Age = 35uy }
|
Number | | Name | Lionel Messi | Team | París Saint-Germain | Position | Forward
| Age | |
|
|
|
2 | (20, [{ Number = 26\n Name = "Nahuel Molina"\n Team = "Atlético de Madrid"\n Position = Defender\n Age = 24uy }; { Number = 13\n Name = "Cristian Romero"\n Team = "Tottenham"\n Position = Defender\n Age = 24uy }; { Number = 25\n Name = "Lisandro Martínez"\n Team = "Manchester United"\n Po...
|
Item1 | | Item2 | index | value |
---|
0 | { Number = 26\n Name = "Nahuel Molina"\n Team = "Atlético de Madrid"\n Position = Defender\n Age = 24uy }
|
Number | | Name | Nahuel Molina | Team | Atlético de Madrid | Position | Defender
| Age | |
| 1 | { Number = 13\n Name = "Cristian Romero"\n Team = "Tottenham"\n Position = Defender\n Age = 24uy }
|
Number | | Name | Cristian Romero | Team | Tottenham | Position | Defender
| Age | |
| 2 | { Number = 25\n Name = "Lisandro Martínez"\n Team = "Manchester United"\n Position = Defender\n Age = 24uy }
|
Number | | Name | Lisandro Martínez | Team | Manchester United | Position | Defender
| Age | |
| 3 | { Number = 2\n Name = "Juan Foyth"\n Team = "Villarreal"\n Position = Defender\n Age = 24uy }
|
Number | | Name | Juan Foyth | Team | Villarreal | Position | Defender
| Age | |
| 4 | { Number = 20\n Name = "Alexis Mac Allister"\n Team = "Brighton"\n Position = Midfielder\n Age = 23uy }
|
Number | | Name | Alexis Mac Allister | Team | Brighton | Position | Midfielder
| Age | |
| 5 | { Number = 24\n Name = "Enzo Fernández"\n Team = "Benfica"\n Position = Midfielder\n Age = 21uy }
|
Number | | Name | Enzo Fernández | Team | Benfica | Position | Midfielder
| Age | |
| 6 | { Number = 14\n Name = "Exequiel Palacios"\n Team = "Bayer Leverkusen"\n Position = Midfielder\n Age = 24uy }
|
Number | | Name | Exequiel Palacios | Team | Bayer Leverkusen | Position | Midfielder
| Age | |
| 7 | { Number = 16\n Name = "Thiago Almada"\n Team = "Atlanta United"\n Position = Midfielder\n Age = 21uy }
|
Number | | Name | Thiago Almada | Team | Atlanta United | Position | Midfielder
| Age | |
| 8 | { Number = 9\n Name = "Julián Álvarez"\n Team = "Manchester City"\n Position = Forward\n Age = 22uy }
|
Number | | Name | Julián Álvarez | Team | Manchester City | Position | Forward
| Age | |
|
|
|
3 | (25, [{ Number = 4\n Name = "Gonzalo Montiel"\n Team = "Sevilla"\n Position = Defender\n Age = 25uy }; { Number = 7\n Name = "Rodrigo De Paul"\n Team = "Atlético de Madrid"\n Position = Midfielder\n Age = 28uy }; { Number = 5\n Name = "Leandro Paredes"\n Team = "Juventus"\n Position = Mid...
|
Item1 | | Item2 | index | value |
---|
0 | { Number = 4\n Name = "Gonzalo Montiel"\n Team = "Sevilla"\n Position = Defender\n Age = 25uy }
|
Number | | Name | Gonzalo Montiel | Team | Sevilla | Position | Defender
| Age | |
| 1 | { Number = 7\n Name = "Rodrigo De Paul"\n Team = "Atlético de Madrid"\n Position = Midfielder\n Age = 28uy }
|
Number | | Name | Rodrigo De Paul | Team | Atlético de Madrid | Position | Midfielder
| Age | |
| 2 | { Number = 5\n Name = "Leandro Paredes"\n Team = "Juventus"\n Position = Midfielder\n Age = 28uy }
|
Number | | Name | Leandro Paredes | Team | Juventus | Position | Midfielder
| Age | |
| 3 | { Number = 18\n Name = "Guido Rodríguez"\n Team = "Betis"\n Position = Midfielder\n Age = 28uy }
|
Number | | Name | Guido Rodríguez | Team | Betis | Position | Midfielder
| Age | |
| 4 | { Number = 22\n Name = "Lautaro Martínez"\n Team = "Inter"\n Position = Forward\n Age = 25uy }
|
Number | | Name | Lautaro Martínez | Team | Inter | Position | Forward
| Age | |
| 5 | { Number = 21\n Name = "Paulo Dybala"\n Team = "Roma"\n Position = Forward\n Age = 29uy }
|
Number | | Name | Paulo Dybala | Team | Roma | Position | Forward
| Age | |
| 6 | { Number = 15\n Name = "Ángel Correa"\n Team = "Atlético Madrid"\n Position = Forward\n Age = 27uy }
|
Number | | Name | Ángel Correa | Team | Atlético Madrid | Position | Forward
| Age | |
|
|
|
champions2022
|> List.groupBy (fun p -> p.Age/5uy * 5uy)
|> List.map (fun (t,l) -> (t, l.Length))
|> List.sort
index | value |
---|
0 | (20, 9)
|
1 | (25, 7)
|
2 | (30, 8)
|
3 | (35, 2)
|
La función List.partition
nos permite agrupar los elementos en dos listas con características disjuntas:
champions2022
|> List.map (fun p -> (p.Name,p.Age))
|> List.partition (fun (name,age) -> age < 30uy)
([(Nahuel Molina, 24); (Gonzalo Montiel, 25); (Cristian Romero, 24); ... ], [(Emiliano Martínez, 30); (Gerónimo Rulli, 30); (Franco Armani, 36); ... ])
|
Item1 | index | value |
---|
0 | (Nahuel Molina, 24)
| 1 | (Gonzalo Montiel, 25)
|
Item1 | Gonzalo Montiel | Item2 | |
| 2 | (Cristian Romero, 24)
|
Item1 | Cristian Romero | Item2 | |
| 3 | (Lisandro Martínez, 24)
|
Item1 | Lisandro Martínez | Item2 | |
| 4 | (Juan Foyth, 24)
| 5 | (Rodrigo De Paul, 28)
|
Item1 | Rodrigo De Paul | Item2 | |
| 6 | (Leandro Paredes, 28)
|
Item1 | Leandro Paredes | Item2 | |
| 7 | (Alexis Mac Allister, 23)
|
Item1 | Alexis Mac Allister | Item2 | |
| 8 | (Guido Rodríguez, 28)
|
Item1 | Guido Rodríguez | Item2 | |
| 9 | (Enzo Fernández, 21)
| 10 | (Exequiel Palacios, 24)
|
Item1 | Exequiel Palacios | Item2 | |
| 11 | (Thiago Almada, 21)
| 12 | (Lautaro Martínez, 25)
|
Item1 | Lautaro Martínez | Item2 | |
| 13 | (Julián Álvarez, 22)
| 14 | (Paulo Dybala, 29)
| 15 | (Ángel Correa, 27)
|
|
Item2 | index | value |
---|
0 | (Emiliano Martínez, 30)
|
Item1 | Emiliano Martínez | Item2 | |
| 1 | (Gerónimo Rulli, 30)
| 2 | (Franco Armani, 36)
| 3 | (Germán Pezzella, 31)
|
Item1 | Germán Pezzella | Item2 | |
| 4 | (Nicolás Otamendi, 34)
|
Item1 | Nicolás Otamendi | Item2 | |
| 5 | (Marcos Acuña, 31)
| 6 | (Nicolás Tagliafico, 30)
|
Item1 | Nicolás Tagliafico | Item2 | |
| 7 | (Alejandro Gómez, 34)
|
Item1 | Alejandro Gómez | Item2 | |
| 8 | (Ángel Di María, 34)
| 9 | (Lionel Messi, 35)
|
|
let menoresde30, mayoresde30 =
champions2022
|> List.map (fun p -> (p.Name,p.Age))
|> List.partition (fun (name,age) -> age < 30uy)
printfn $"Los menores de 30 son {menoresde30.Length}"
printfn $"Los mayores de 30 son {mayoresde30.Length}"
Los menores de 30 son 16
Los mayores de 30 son 10
Finalmente, algunas funciones nos permiten evaluar una determinada característica de una lista:
champions2022
|> List.forall (fun p -> p.Age < 30uy)
menoresde30
|> List.forall (fun (_,a) -> a < 30uy)