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 []        
empty
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) 
1
1
[2; 3]
[2; 3]

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:

printfn "%A" [].Head 
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)
printfn "%A" [].Tail
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
[3; 6; 7]

o concatenando dos listas:

let l2 = l @ [8;9]
printfn "%A" l2
[3; 6; 7; 8; 9]

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
24
NameEnzo Fernández
TeamBenfica
Position
Midfielder
Age
21
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
16
NameThiago Almada
TeamAtlanta United
Position
Midfielder
Age
21
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)
indexvalue
0
{ Number = 24\n Name = "Enzo Fernández"\n Team = "Benfica"\n Position = Midfielder\n Age = 21uy }
Number
24
NameEnzo Fernández
TeamBenfica
Position
Midfielder
Age
21
1
{ Number = 16\n Name = "Thiago Almada"\n Team = "Atlanta United"\n Position = Midfielder\n Age = 21uy }
Number
16
NameThiago Almada
TeamAtlanta United
Position
Midfielder
Age
21
champions2022
|> List.filter (fun p -> p.Age > 25uy && p.Position = Defender)
indexvalue
0
{ Number = 6\n Name = "Germán Pezzella"\n Team = "Betis"\n Position = Defender\n Age = 31uy }
Number
6
NameGermán Pezzella
TeamBetis
Position
Defender
Age
31
1
{ Number = 19\n Name = "Nicolás Otamendi"\n Team = "Benfica"\n Position = Defender\n Age = 34uy }
Number
19
NameNicolás Otamendi
TeamBenfica
Position
Defender
Age
34
2
{ Number = 8\n Name = "Marcos Acuña"\n Team = "Sevilla"\n Position = Defender\n Age = 31uy }
Number
8
NameMarcos Acuña
TeamSevilla
Position
Defender
Age
31
3
{ Number = 3\n Name = "Nicolás Tagliafico"\n Team = "Olympique de Lyon"\n Position = Defender\n Age = 30uy }
Number
3
NameNicolás Tagliafico
TeamOlympique de Lyon
Position
Defender
Age
30
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)
27.76923076923077

Hay funciones que permiten procesar la lista, recolectando datos que poseen características similares.

champions2022
|> List.groupBy (fun p -> p.Team)
indexvalue
0
(Aston Villa, [{ Number = 23\n Name = "Emiliano Martínez"\n Team = "Aston Villa"\n Position = GoalKeeper\n Age = 30uy }])
Item1Aston Villa
Item2
indexvalue
0
{ Number = 23\n Name = "Emiliano Martínez"\n Team = "Aston Villa"\n Position = GoalKeeper\n Age = 30uy }
Number
23
NameEmiliano Martínez
TeamAston Villa
Position
GoalKeeper
Age
30
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 }])
Item1Villarreal
Item2
indexvalue
0
{ Number = 12\n Name = "Gerónimo Rulli"\n Team = "Villarreal"\n Position = GoalKeeper\n Age = 30uy }
Number
12
NameGerónimo Rulli
TeamVillarreal
Position
GoalKeeper
Age
30
1
{ Number = 2\n Name = "Juan Foyth"\n Team = "Villarreal"\n Position = Defender\n Age = 24uy }
Number
2
NameJuan Foyth
TeamVillarreal
Position
Defender
Age
24
2
(River, [{ Number = 1\n Name = "Franco Armani"\n Team = "River"\n Position = GoalKeeper\n Age = 36uy }])
Item1River
Item2
indexvalue
0
{ Number = 1\n Name = "Franco Armani"\n Team = "River"\n Position = GoalKeeper\n Age = 36uy }
Number
1
NameFranco Armani
TeamRiver
Position
GoalKeeper
Age
36
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 }])
Item1Atlético de Madrid
Item2
indexvalue
0
{ Number = 26\n Name = "Nahuel Molina"\n Team = "Atlético de Madrid"\n Position = Defender\n Age = 24uy }
Number
26
NameNahuel Molina
TeamAtlético de Madrid
Position
Defender
Age
24
1
{ Number = 7\n Name = "Rodrigo De Paul"\n Team = "Atlético de Madrid"\n Position = Midfielder\n Age = 28uy }
Number
7
NameRodrigo De Paul
TeamAtlético de Madrid
Position
Midfielder
Age
28
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 ...
Item1Sevilla
Item2
indexvalue
0
{ Number = 4\n Name = "Gonzalo Montiel"\n Team = "Sevilla"\n Position = Defender\n Age = 25uy }
Number
4
NameGonzalo Montiel
TeamSevilla
Position
Defender
Age
25
1
{ Number = 8\n Name = "Marcos Acuña"\n Team = "Sevilla"\n Position = Defender\n Age = 31uy }
Number
8
NameMarcos Acuña
TeamSevilla
Position
Defender
Age
31
2
{ Number = 17\n Name = "Alejandro Gómez"\n Team = "Sevilla"\n Position = Midfielder\n Age = 34uy }
Number
17
NameAlejandro Gómez
TeamSevilla
Position
Midfielder
Age
34
5
(Tottenham, [{ Number = 13\n Name = "Cristian Romero"\n Team = "Tottenham"\n Position = Defender\n Age = 24uy }])
Item1Tottenham
Item2
indexvalue
0
{ Number = 13\n Name = "Cristian Romero"\n Team = "Tottenham"\n Position = Defender\n Age = 24uy }
Number
13
NameCristian Romero
TeamTottenham
Position
Defender
Age
24
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 }])
Item1Betis
Item2
indexvalue
0
{ Number = 6\n Name = "Germán Pezzella"\n Team = "Betis"\n Position = Defender\n Age = 31uy }
Number
6
NameGermán Pezzella
TeamBetis
Position
Defender
Age
31
1
{ Number = 18\n Name = "Guido Rodríguez"\n Team = "Betis"\n Position = Midfielder\n Age = 28uy }
Number
18
NameGuido Rodríguez
TeamBetis
Position
Midfielder
Age
28
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 }])
Item1Benfica
Item2
indexvalue
0
{ Number = 19\n Name = "Nicolás Otamendi"\n Team = "Benfica"\n Position = Defender\n Age = 34uy }
Number
19
NameNicolás Otamendi
TeamBenfica
Position
Defender
Age
34
1
{ Number = 24\n Name = "Enzo Fernández"\n Team = "Benfica"\n Position = Midfielder\n Age = 21uy }
Number
24
NameEnzo Fernández
TeamBenfica
Position
Midfielder
Age
21
8
(Manchester United, [{ Number = 25\n Name = "Lisandro Martínez"\n Team = "Manchester United"\n Position = Defender\n Age = 24uy }])
Item1Manchester United
Item2
indexvalue
0
{ Number = 25\n Name = "Lisandro Martínez"\n Team = "Manchester United"\n Position = Defender\n Age = 24uy }
Number
25
NameLisandro Martínez
TeamManchester United
Position
Defender
Age
24
9
(Olympique de Lyon, [{ Number = 3\n Name = "Nicolás Tagliafico"\n Team = "Olympique de Lyon"\n Position = Defender\n Age = 30uy }])
Item1Olympique de Lyon
Item2
indexvalue
0
{ Number = 3\n Name = "Nicolás Tagliafico"\n Team = "Olympique de Lyon"\n Position = Defender\n Age = 30uy }
Number
3
NameNicolás Tagliafico
TeamOlympique de Lyon
Position
Defender
Age
30
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 }])
Item1Juventus
Item2
indexvalue
0
{ Number = 5\n Name = "Leandro Paredes"\n Team = "Juventus"\n Position = Midfielder\n Age = 28uy }
Number
5
NameLeandro Paredes
TeamJuventus
Position
Midfielder
Age
28
1
{ Number = 11\n Name = "Ángel Di María"\n Team = "Juventus"\n Position = Forward\n Age = 34uy }
Number
11
NameÁngel Di María
TeamJuventus
Position
Forward
Age
34
11
(Brighton, [{ Number = 20\n Name = "Alexis Mac Allister"\n Team = "Brighton"\n Position = Midfielder\n Age = 23uy }])
Item1Brighton
Item2
indexvalue
0
{ Number = 20\n Name = "Alexis Mac Allister"\n Team = "Brighton"\n Position = Midfielder\n Age = 23uy }
Number
20
NameAlexis Mac Allister
TeamBrighton
Position
Midfielder
Age
23
12
(Bayer Leverkusen, [{ Number = 14\n Name = "Exequiel Palacios"\n Team = "Bayer Leverkusen"\n Position = Midfielder\n Age = 24uy }])
Item1Bayer Leverkusen
Item2
indexvalue
0
{ Number = 14\n Name = "Exequiel Palacios"\n Team = "Bayer Leverkusen"\n Position = Midfielder\n Age = 24uy }
Number
14
NameExequiel Palacios
TeamBayer Leverkusen
Position
Midfielder
Age
24
13
(Atlanta United, [{ Number = 16\n Name = "Thiago Almada"\n Team = "Atlanta United"\n Position = Midfielder\n Age = 21uy }])
Item1Atlanta United
Item2
indexvalue
0
{ Number = 16\n Name = "Thiago Almada"\n Team = "Atlanta United"\n Position = Midfielder\n Age = 21uy }
Number
16
NameThiago Almada
TeamAtlanta United
Position
Midfielder
Age
21
14
(Inter, [{ Number = 22\n Name = "Lautaro Martínez"\n Team = "Inter"\n Position = Forward\n Age = 25uy }])
Item1Inter
Item2
indexvalue
0
{ Number = 22\n Name = "Lautaro Martínez"\n Team = "Inter"\n Position = Forward\n Age = 25uy }
Number
22
NameLautaro Martínez
TeamInter
Position
Forward
Age
25
15
(Manchester City, [{ Number = 9\n Name = "Julián Álvarez"\n Team = "Manchester City"\n Position = Forward\n Age = 22uy }])
Item1Manchester City
Item2
indexvalue
0
{ Number = 9\n Name = "Julián Álvarez"\n Team = "Manchester City"\n Position = Forward\n Age = 22uy }
Number
9
NameJulián Álvarez
TeamManchester City
Position
Forward
Age
22
16
(Roma, [{ Number = 21\n Name = "Paulo Dybala"\n Team = "Roma"\n Position = Forward\n Age = 29uy }])
Item1Roma
Item2
indexvalue
0
{ Number = 21\n Name = "Paulo Dybala"\n Team = "Roma"\n Position = Forward\n Age = 29uy }
Number
21
NamePaulo Dybala
TeamRoma
Position
Forward
Age
29
17
(Atlético Madrid, [{ Number = 15\n Name = "Ángel Correa"\n Team = "Atlético Madrid"\n Position = Forward\n Age = 27uy }])
Item1Atlético Madrid
Item2
indexvalue
0
{ Number = 15\n Name = "Ángel Correa"\n Team = "Atlético Madrid"\n Position = Forward\n Age = 27uy }
Number
15
NameÁngel Correa
TeamAtlético Madrid
Position
Forward
Age
27
18
(París Saint-Germain, [{ Number = 10\n Name = "Lionel Messi"\n Team = "París Saint-Germain"\n Position = Forward\n Age = 35uy }])
Item1París Saint-Germain
Item2
indexvalue
0
{ Number = 10\n Name = "Lionel Messi"\n Team = "París Saint-Germain"\n Position = Forward\n Age = 35uy }
Number
10
NameLionel Messi
TeamParís Saint-Germain
Position
Forward
Age
35

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))

indexvalue
0
(Aston Villa, 1)
Item1Aston Villa
Item2
1
1
(Villarreal, 2)
Item1Villarreal
Item2
2
2
(River, 1)
Item1River
Item2
1
3
(Atlético de Madrid, 2)
Item1Atlético de Madrid
Item2
2
4
(Sevilla, 3)
Item1Sevilla
Item2
3
5
(Tottenham, 1)
Item1Tottenham
Item2
1
6
(Betis, 2)
Item1Betis
Item2
2
7
(Benfica, 2)
Item1Benfica
Item2
2
8
(Manchester United, 1)
Item1Manchester United
Item2
1
9
(Olympique de Lyon, 1)
Item1Olympique de Lyon
Item2
1
10
(Juventus, 2)
Item1Juventus
Item2
2
11
(Brighton, 1)
Item1Brighton
Item2
1
12
(Bayer Leverkusen, 1)
Item1Bayer Leverkusen
Item2
1
13
(Atlanta United, 1)
Item1Atlanta United
Item2
1
14
(Inter, 1)
Item1Inter
Item2
1
15
(Manchester City, 1)
Item1Manchester City
Item2
1
16
(Roma, 1)
Item1Roma
Item2
1
17
(Atlético Madrid, 1)
Item1Atlético Madrid
Item2
1
18
(París Saint-Germain, 1)
Item1París Saint-Germain
Item2
1

Este último procedimiento se puede resumir con List.countBy:

champions2022
|> List.countBy (fun p -> p.Team)
indexvalue
0
(Aston Villa, 1)
Item1Aston Villa
Item2
1
1
(Villarreal, 2)
Item1Villarreal
Item2
2
2
(River, 1)
Item1River
Item2
1
3
(Atlético de Madrid, 2)
Item1Atlético de Madrid
Item2
2
4
(Sevilla, 3)
Item1Sevilla
Item2
3
5
(Tottenham, 1)
Item1Tottenham
Item2
1
6
(Betis, 2)
Item1Betis
Item2
2
7
(Benfica, 2)
Item1Benfica
Item2
2
8
(Manchester United, 1)
Item1Manchester United
Item2
1
9
(Olympique de Lyon, 1)
Item1Olympique de Lyon
Item2
1
10
(Juventus, 2)
Item1Juventus
Item2
2
11
(Brighton, 1)
Item1Brighton
Item2
1
12
(Bayer Leverkusen, 1)
Item1Bayer Leverkusen
Item2
1
13
(Atlanta United, 1)
Item1Atlanta United
Item2
1
14
(Inter, 1)
Item1Inter
Item2
1
15
(Manchester City, 1)
Item1Manchester City
Item2
1
16
(Roma, 1)
Item1Roma
Item2
1
17
(Atlético Madrid, 1)
Item1Atlético Madrid
Item2
1
18
(París Saint-Germain, 1)
Item1París Saint-Germain
Item2
1

Se puede construir un histograma de edades:

champions2022
|> List.groupBy (fun p -> p.Age/5uy * 5uy)

indexvalue
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
30
Item2
indexvalue
0
{ Number = 23\n Name = "Emiliano Martínez"\n Team = "Aston Villa"\n Position = GoalKeeper\n Age = 30uy }
Number
23
NameEmiliano Martínez
TeamAston Villa
Position
GoalKeeper
Age
30
1
{ Number = 12\n Name = "Gerónimo Rulli"\n Team = "Villarreal"\n Position = GoalKeeper\n Age = 30uy }
Number
12
NameGerónimo Rulli
TeamVillarreal
Position
GoalKeeper
Age
30
2
{ Number = 6\n Name = "Germán Pezzella"\n Team = "Betis"\n Position = Defender\n Age = 31uy }
Number
6
NameGermán Pezzella
TeamBetis
Position
Defender
Age
31
3
{ Number = 19\n Name = "Nicolás Otamendi"\n Team = "Benfica"\n Position = Defender\n Age = 34uy }
Number
19
NameNicolás Otamendi
TeamBenfica
Position
Defender
Age
34
4
{ Number = 8\n Name = "Marcos Acuña"\n Team = "Sevilla"\n Position = Defender\n Age = 31uy }
Number
8
NameMarcos Acuña
TeamSevilla
Position
Defender
Age
31
5
{ Number = 3\n Name = "Nicolás Tagliafico"\n Team = "Olympique de Lyon"\n Position = Defender\n Age = 30uy }
Number
3
NameNicolás Tagliafico
TeamOlympique de Lyon
Position
Defender
Age
30
6
{ Number = 17\n Name = "Alejandro Gómez"\n Team = "Sevilla"\n Position = Midfielder\n Age = 34uy }
Number
17
NameAlejandro Gómez
TeamSevilla
Position
Midfielder
Age
34
7
{ Number = 11\n Name = "Ángel Di María"\n Team = "Juventus"\n Position = Forward\n Age = 34uy }
Number
11
NameÁngel Di María
TeamJuventus
Position
Forward
Age
34
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
35
Item2
indexvalue
0
{ Number = 1\n Name = "Franco Armani"\n Team = "River"\n Position = GoalKeeper\n Age = 36uy }
Number
1
NameFranco Armani
TeamRiver
Position
GoalKeeper
Age
36
1
{ Number = 10\n Name = "Lionel Messi"\n Team = "París Saint-Germain"\n Position = Forward\n Age = 35uy }
Number
10
NameLionel Messi
TeamParís Saint-Germain
Position
Forward
Age
35
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
20
Item2
indexvalue
0
{ Number = 26\n Name = "Nahuel Molina"\n Team = "Atlético de Madrid"\n Position = Defender\n Age = 24uy }
Number
26
NameNahuel Molina
TeamAtlético de Madrid
Position
Defender
Age
24
1
{ Number = 13\n Name = "Cristian Romero"\n Team = "Tottenham"\n Position = Defender\n Age = 24uy }
Number
13
NameCristian Romero
TeamTottenham
Position
Defender
Age
24
2
{ Number = 25\n Name = "Lisandro Martínez"\n Team = "Manchester United"\n Position = Defender\n Age = 24uy }
Number
25
NameLisandro Martínez
TeamManchester United
Position
Defender
Age
24
3
{ Number = 2\n Name = "Juan Foyth"\n Team = "Villarreal"\n Position = Defender\n Age = 24uy }
Number
2
NameJuan Foyth
TeamVillarreal
Position
Defender
Age
24
4
{ Number = 20\n Name = "Alexis Mac Allister"\n Team = "Brighton"\n Position = Midfielder\n Age = 23uy }
Number
20
NameAlexis Mac Allister
TeamBrighton
Position
Midfielder
Age
23
5
{ Number = 24\n Name = "Enzo Fernández"\n Team = "Benfica"\n Position = Midfielder\n Age = 21uy }
Number
24
NameEnzo Fernández
TeamBenfica
Position
Midfielder
Age
21
6
{ Number = 14\n Name = "Exequiel Palacios"\n Team = "Bayer Leverkusen"\n Position = Midfielder\n Age = 24uy }
Number
14
NameExequiel Palacios
TeamBayer Leverkusen
Position
Midfielder
Age
24
7
{ Number = 16\n Name = "Thiago Almada"\n Team = "Atlanta United"\n Position = Midfielder\n Age = 21uy }
Number
16
NameThiago Almada
TeamAtlanta United
Position
Midfielder
Age
21
8
{ Number = 9\n Name = "Julián Álvarez"\n Team = "Manchester City"\n Position = Forward\n Age = 22uy }
Number
9
NameJulián Álvarez
TeamManchester City
Position
Forward
Age
22
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
25
Item2
indexvalue
0
{ Number = 4\n Name = "Gonzalo Montiel"\n Team = "Sevilla"\n Position = Defender\n Age = 25uy }
Number
4
NameGonzalo Montiel
TeamSevilla
Position
Defender
Age
25
1
{ Number = 7\n Name = "Rodrigo De Paul"\n Team = "Atlético de Madrid"\n Position = Midfielder\n Age = 28uy }
Number
7
NameRodrigo De Paul
TeamAtlético de Madrid
Position
Midfielder
Age
28
2
{ Number = 5\n Name = "Leandro Paredes"\n Team = "Juventus"\n Position = Midfielder\n Age = 28uy }
Number
5
NameLeandro Paredes
TeamJuventus
Position
Midfielder
Age
28
3
{ Number = 18\n Name = "Guido Rodríguez"\n Team = "Betis"\n Position = Midfielder\n Age = 28uy }
Number
18
NameGuido Rodríguez
TeamBetis
Position
Midfielder
Age
28
4
{ Number = 22\n Name = "Lautaro Martínez"\n Team = "Inter"\n Position = Forward\n Age = 25uy }
Number
22
NameLautaro Martínez
TeamInter
Position
Forward
Age
25
5
{ Number = 21\n Name = "Paulo Dybala"\n Team = "Roma"\n Position = Forward\n Age = 29uy }
Number
21
NamePaulo Dybala
TeamRoma
Position
Forward
Age
29
6
{ Number = 15\n Name = "Ángel Correa"\n Team = "Atlético Madrid"\n Position = Forward\n Age = 27uy }
Number
15
NameÁngel Correa
TeamAtlético Madrid
Position
Forward
Age
27
champions2022
|> List.groupBy (fun p -> p.Age/5uy * 5uy)
|> List.map (fun (t,l) -> (t, l.Length))
|> List.sort 
indexvalue
0
(20, 9)
Item1
20
Item2
9
1
(25, 7)
Item1
25
Item2
7
2
(30, 8)
Item1
30
Item2
8
3
(35, 2)
Item1
35
Item2
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
indexvalue
0
(Nahuel Molina, 24)
Item1Nahuel Molina
Item2
24
1
(Gonzalo Montiel, 25)
Item1Gonzalo Montiel
Item2
25
2
(Cristian Romero, 24)
Item1Cristian Romero
Item2
24
3
(Lisandro Martínez, 24)
Item1Lisandro Martínez
Item2
24
4
(Juan Foyth, 24)
Item1Juan Foyth
Item2
24
5
(Rodrigo De Paul, 28)
Item1Rodrigo De Paul
Item2
28
6
(Leandro Paredes, 28)
Item1Leandro Paredes
Item2
28
7
(Alexis Mac Allister, 23)
Item1Alexis Mac Allister
Item2
23
8
(Guido Rodríguez, 28)
Item1Guido Rodríguez
Item2
28
9
(Enzo Fernández, 21)
Item1Enzo Fernández
Item2
21
10
(Exequiel Palacios, 24)
Item1Exequiel Palacios
Item2
24
11
(Thiago Almada, 21)
Item1Thiago Almada
Item2
21
12
(Lautaro Martínez, 25)
Item1Lautaro Martínez
Item2
25
13
(Julián Álvarez, 22)
Item1Julián Álvarez
Item2
22
14
(Paulo Dybala, 29)
Item1Paulo Dybala
Item2
29
15
(Ángel Correa, 27)
Item1Ángel Correa
Item2
27
Item2
indexvalue
0
(Emiliano Martínez, 30)
Item1Emiliano Martínez
Item2
30
1
(Gerónimo Rulli, 30)
Item1Gerónimo Rulli
Item2
30
2
(Franco Armani, 36)
Item1Franco Armani
Item2
36
3
(Germán Pezzella, 31)
Item1Germán Pezzella
Item2
31
4
(Nicolás Otamendi, 34)
Item1Nicolás Otamendi
Item2
34
5
(Marcos Acuña, 31)
Item1Marcos Acuña
Item2
31
6
(Nicolás Tagliafico, 30)
Item1Nicolás Tagliafico
Item2
30
7
(Alejandro Gómez, 34)
Item1Alejandro Gómez
Item2
34
8
(Ángel Di María, 34)
Item1Ángel Di María
Item2
34
9
(Lionel Messi, 35)
Item1Lionel Messi
Item2
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)
False
menoresde30
|> List.forall (fun (_,a) -> a < 30uy)

False
List.findIndex

results matching ""

    No results matching ""