Realización de operaciones en listas
Si almacena muchos elementos en una lista, a menudo realizará operaciones en parte o en la totalidad de la lista. El módulo de lista contiene muchas operaciones útiles que le permiten hacerlo.
Funciones del módulo de lista
Además de las propiedades, hay un módulo repleto de funciones para realizar en una lista. Las funciones pueden realizar operaciones de uso frecuente, como buscar, filtrar, ordenar, realizar operaciones matemáticas, etc.
Iteración
"Iterar" significa recorrer cada elemento de una lista desde un punto inicial hasta un punto final. Para la iteración hay dos funciones especialmente interesantes:
iter()
: esta función le permite recorrer en iteración cada elemento de una lista, como se muestra aquí:let cards = [ 1 .. 5 ] List.iter(fun i -> printfn "%i" i) cards // 1 2 3 4 5
La función
iter()
toma una función. En el código anterior, se proporciona una función anónima mediante la palabra clavefun
. Esta función toma un parámetro que representa el elemento actual a medida que se itera. Este código equivale a escribir el siguiente con un bucle:for i in cards do printfn "%i" i
map()
: esta función es similar aiter()
, pero permite transformar lo que tiene. Este es un ejemplo:type Person = { FirstName: string; LastName: string } let people = [ { FirstName="Albert"; LastName= "Einstein" } { FirstName="Marie"; LastName="Curie" } ] let nobelPrizeWinners = List.map (fun person -> person.FirstName + person.LastName) people printfn "%A" nobelPrizeWinners // ["Albert Einstein"; "Marie Curie"]
En el código anterior, la lista de objetos
Person
se transforma en una lista de cadenas.
Filter
La función filter()
también toma una función como parámetro, pero su propósito es definir los elementos que se conservarán. Si la evaluación de la expresión es true
, se mantiene el elemento. Si la expresión es false
, el elemento no formará parte de la lista filtrada. En el ejemplo siguiente, se filtra una lista para mantener solo los elementos cuyo valor es divisible por dos:
let cards = [ 1 .. 5 ]
let filteredList = List.filter(fun i-> i % 2 = 0) cards
List.iter(fun i -> printfn "item %i" i) filteredList // item 2 item 4
Ahora, la lista filteredList
solo contiene los elementos que han devuelto true
al evaluarse según i % 2 = 0
, es decir, 2 y 4.
Sort
Ordenar listas es algo que probablemente haga con frecuencia. Estas son tres funciones que pueden resultar útiles al ordenar listas:
sort()
ordena de forma ascendente. Este es un ejemplo:let list = [2; 1; 5; 3] let sortedList = List.sort list // 1 2 3 5
sortBy()
: con esta función, la idea es indicar una clave por la que ordenar. Supongamos que tiene una lista de personas y cada registro tiene los camposname
yage
. A continuación, puede indicar que se ordene porage
, por ejemplo. Esta función toma una función en la que se señala la clave. Otra clave podría ser la longitud de una cadena, como en este ejemplo:let fruits = ["Banana"; "Apple"; "Pineapple"] let sortedFruits = List.sortBy (fun (fruit : string) -> fruit.Length) fruits // Apple, Banana, Pineapple
sortWith()
: con esta función, puede proporcionar una función de comparador, ya que es posible que no sea evidente al principio cuál de varios elementos debe ordenarse antes que cualquier otro. A continuación, se ponen ejemplos de código:// assume a type like so type MagicCreature = { Name : string; Level: int; Attack: int } let creatures = [ { Name="Dragon"; Level=2; Attack=20 } { Name="Orc"; Level=1; Attack=5 } { Name="Demon"; Level=2; Attack=10 } ] // comparison function, -1 = less than, 1 = larger than, 0 = equal let compareCreatures c1 c2 = if c1.Level < c2.Level then -1 else if c1.Level > c2.Level then 1 else if c1.Attack < c2.Attack then -1 else if c1.Attack > c2.Attack then 1 else 0 let sorted = List.sortWith compareCreatures creatures // { Name="Orc"; Level=1; Attack=5 }, { Name="Demon"; Level=2; Attack=10 }, { Name="Dragon"; Level=2; Attack=20 }
La función de comparación anterior,
compareCreatures()
, intenta comparar primero medianteLevel
. Si el nivel es igual, intenta comparar medianteAttack
. Devuelve-1
si algo se considera más pequeño,1
si es mayor y0
si es igual.
Búsqueda
Otra cosa que puede querer hacer es buscar un elemento específico. Para ello, puede elegir entre las funciones siguientes:
find()
: esta función busca el primer elemento que coincide con una condición determinada. Para usarfind()
, debe proporcionar una función (predicado) que exprese cómo encontrar el elemento. Este es un ejemplo:let list = [1; 2; 3; 4] let found = List.find( fun x -> x % 2 = 0) list // 2 - Only the first element that matches the condition is returned.
tryFind()
. Esta función toma una función (predicado) que indica cómo buscar el valor y una lista en la que buscar. Devuelve una opción. A continuación, se muestra cómo puede usarla:let findValue aValue aList = let found = aList |> List.tryFind(fun item -> item = aValue) match found with | Some value -> printfn "%i" value | None -> printfn "Not found" findValue 1 list // 1 findValue 5 list // Not found
En el código anterior, envía un valor para compararlo con su lista. Si se encuentra, devuelve
Some
. Si no se encuentra, devuelveNone
.tryFindIndex()
. Al igual quetryFind()
, esta función devuelve una opción y toma una función (predicado) que se evalúa como valor booleano. El código tendría el aspecto siguiente:let found = List.tryFindIndex(fun x -> x = 4) list match found with | Some index -> printfn "%i" index | None -> printfn "Not found"
Operaciones aritméticas
Realizar operaciones matemáticas en una lista puede ser útil. De las muchas funciones entre las que elegir en la API de listas, estas son las tres más útiles:
sum()
: con esta función, se recorre en iteración cada elemento para sumar todos los valores de la lista. A continuación, se muestra cómo puede usarla:let sum = List.sum [1 .. 5] // sum = 15
sumBy()
: con esta función, la idea es indicar cómo sumar los valores. Una forma de hacerlo es indicar qué campos sumar, como en el ejemplo siguiente:type OrderItem = { Name: string; Cost:int } let orderItems = [ { Name="XBox"; Cost=500 } { Name="Book"; Cost=10 } { Name="Movie ticket"; Cost=7 } ] let sum = List.sumBy(fun item -> item.Cost) orderItems printfn "%i" sum // 517
En el código anterior, se indica el campo
Cost
y cada elemento de ese campo se suma al total.average()
: esta función es similar asum()
en la medida que funciona en una lista de números, pero presenta dos diferencias:- Espera que los datos sean números de punto flotante, no enteros.
- Calcula un promedio en lugar de una suma.
Este es un ejemplo:
let numbers = [ 1.0; 2.5; 3.0 ] let avg = List.average numbers printfn "%f" avg // 2.166667
averageBy()
:sumBy()
, al igual queaverageBy()
, toma una función donde se especifica el valor que desea. Este es un ejemplo:type WeatherMeasurement = { Date: string; Temperature: float } let measurements = [ { Date="07/20/2021"; Temperature=21.3 } { Date="07/21/2021"; Temperature=23.2 } { Date="07/22/2021"; Temperature=20.7 } ] let avgBy = List.averageBy(fun m -> m.Temperature) measurements printfn "%f" avgBy // 21.733333