ListasLists
Nota
Los vínculos de la referencia de API de este artículo le llevarán a MSDN.The API reference links in this article will take you to MSDN. La referencia de API de docs.microsoft.com no está completa.The docs.microsoft.com API reference is not complete.
En F#, una lista es una serie ordenada e inmutable de elementos del mismo tipo.A list in F# is an ordered, immutable series of elements of the same type. Para realizar operaciones básicas en listas, use las funciones del módulo de lista.To perform basic operations on lists, use the functions in the List module.
Crear e inicializar listasCreating and Initializing Lists
Para definir una lista, puede enumerar explícitamente los elementos, separados por punto y coma y escritos entre corchetes, tal y como se muestra en la línea de código siguiente.You can define a list by explicitly listing out the elements, separated by semicolons and enclosed in square brackets, as shown in the following line of code.
let list123 = [ 1; 2; 3 ]
También puede insertar saltos de línea entre los elementos, en cuyo caso el signo de punto y coma es opcional.You can also put line breaks between elements, in which case the semicolons are optional. La última sintaxis produce un código más legible cuando las expresiones de inicialización de elementos son más largas o si quiere incluir un comentario para cada elemento.The latter syntax can result in more readable code when the element initialization expressions are longer, or when you want to include a comment for each element.
let list123 = [
1
2
3 ]
Normalmente, todos los elementos de lista deben ser del mismo tipo.Normally, all list elements must be the same type. Una excepción es que una lista en la cual los elementos se han especificado para que sean de un tipo base puede tener elementos que sean de tipos derivados.An exception is that a list in which the elements are specified to be a base type can have elements that are derived types. Por lo tanto, lo siguiente es aceptable, porque tanto Button
como CheckBox
derivan de Control
.Thus the following is acceptable, because both Button
and CheckBox
derive from Control
.
let myControlList : Control list = [ new Button(); new CheckBox() ]
También puede definir elementos de lista usando un intervalo indicado por enteros separados por el operador de intervalo (..
), tal y como se muestra en el código siguiente.You can also define list elements by using a range indicated by integers separated by the range operator (..
), as shown in the following code.
let list1 = [ 1 .. 10 ]
Una lista vacía se especifica por un par de corchetes con nada entre ellos.An empty list is specified by a pair of square brackets with nothing in between them.
// An empty list.
let listEmpty = []
También puede usar una expresión de secuencia para crear una lista.You can also use a sequence expression to create a list. Vea expresiones de secuencia para obtener más información.See Sequence Expressions for more information. Por ejemplo, el código siguiente crea una lista de cuadrados de enteros, de 1 a 10.For example, the following code creates a list of squares of integers from 1 to 10.
let listOfSquares = [ for i in 1 .. 10 -> i*i ]
Operadores para trabajar con listasOperators for Working with Lists
Puede asociar elementos a una lista usando el operador ::
(cons).You can attach elements to a list by using the ::
(cons) operator. Si list1
es [2; 3; 4]
, el código siguiente crea list2
como [100; 2; 3; 4]
.If list1
is [2; 3; 4]
, the following code creates list2
as [100; 2; 3; 4]
.
let list2 = 100 :: list1
Para concatenar listas que tengan tipos compatibles, puede usar el operador @
, como en el código siguiente.You can concatenate lists that have compatible types by using the @
operator, as in the following code. Si list1
es [2; 3; 4]
y list2
es [100; 2; 3; 4]
, este código crea list3
como [2; 3; 4; 100; 2; 3; 4]
.If list1
is [2; 3; 4]
and list2
is [100; 2; 3; 4]
, this code creates list3
as [2; 3; 4; 100; 2; 3; 4]
.
let list3 = list1 @ list2
Las funciones para realizar operaciones en listas están disponibles en el módulo de lista.Functions for performing operations on lists are available in the List module.
Como en F# las listas son inmutables, las operaciones de modificación generan nuevas listas en lugar de modificar las existentes.Because lists in F# are immutable, any modifying operations generate new lists instead of modifying existing lists.
Las listas F# de se implementan como listas vinculadas individualmente, lo que significa que las operaciones que tienen acceso solo al encabezado de la lista son o (1) y el acceso a los elementos es o (n).Lists in F# are implemented as singly linked lists, which means that operations that access only the head of the list are O(1), and element access is O(n).
PropiedadesProperties
El tipo de lista admite las siguientes propiedades:The list type supports the following properties:
PropiedadProperty | EscribaType | DESCRIPCIÓNDescription |
---|---|---|
HeadHead | 'T |
El primer elemento.The first element. |
VacíaEmpty | 'T list |
Propiedad estática que devuelve una lista vacía del tipo apropiado.A static property that returns an empty list of the appropriate type. |
VacíoIsEmpty | bool |
true si la lista no tiene ningún elemento.true if the list has no elements. |
ElementoItem | 'T |
Elemento en el índice especificado (base cero).The element at the specified index (zero-based). |
LongitudLength | int |
Número de elementos.The number of elements. |
ColaTail | 'T list |
La lista sin el primer elemento.The list without the first element. |
Los siguientes son algunos ejemplos de cómo usar estas propiedades.Following are some examples of using these properties.
let list1 = [ 1; 2; 3 ]
// Properties
printfn "list1.IsEmpty is %b" (list1.IsEmpty)
printfn "list1.Length is %d" (list1.Length)
printfn "list1.Head is %d" (list1.Head)
printfn "list1.Tail.Head is %d" (list1.Tail.Head)
printfn "list1.Tail.Tail.Head is %d" (list1.Tail.Tail.Head)
printfn "list1.Item(1) is %d" (list1.Item(1))
Usar listasUsing Lists
Programar con listas permite realizar operaciones complejas con una pequeña cantidad de código.Programming with lists enables you to perform complex operations with a small amount of code. En esta sección se describen las operaciones comunes en las listas que son importantes para la programación funcional.This section describes common operations on lists that are important to functional programming.
Recursión con listasRecursion with Lists
Las listas están especialmente indicadas para las técnicas de programación recursiva.Lists are uniquely suited to recursive programming techniques. Tomemos una operación que deba realizarse en todos los elementos de una lista.Consider an operation that must be performed on every element of a list. Puede hacerlo recursivamente ejecutando una operación en el encabezado de la lista y, después, devolviendo la cola de la lista (que es una lista más pequeña formada por la lista original sin el primer elemento) de nuevo al siguiente nivel de recursión.You can do this recursively by operating on the head of the list and then passing the tail of the list, which is a smaller list that consists of the original list without the first element, back again to the next level of recursion.
Para escribir una función recursiva de este estilo, se usa el operador cons (::
) en coincidencia de patrones, lo que permite separar el encabezado de una lista de la cola.To write such a recursive function, you use the cons operator (::
) in pattern matching, which enables you to separate the head of a list from the tail.
En el ejemplo de código siguiente se muestra cómo usar la coincidencia de patrones para implementar una función recursiva que realice operaciones en una lista.The following code example shows how to use pattern matching to implement a recursive function that performs operations on a list.
let rec sum list =
match list with
| head :: tail -> head + sum tail
| [] -> 0
El código anterior funciona bien para listas pequeñas, pero en listas mayores podría desbordar la pila.The previous code works well for small lists, but for larger lists, it could overflow the stack. El código siguiente mejora este código usando un argumento acumulador, una técnica estándar para trabajar con funciones recursivas.The following code improves on this code by using an accumulator argument, a standard technique for working with recursive functions. El uso del argumento acumulador hace que la función sea recursiva en la cola, lo que ahorra espacio en la pila.The use of the accumulator argument makes the function tail recursive, which saves stack space.
let sum list =
let rec loop list acc =
match list with
| head :: tail -> loop tail (acc + head)
| [] -> acc
loop list 0
La función RemoveAllMultiples
es una función recursiva que toma dos listas.The function RemoveAllMultiples
is a recursive function that takes two lists. La primera lista contiene los números cuyos múltiplos se van a quitar, y la segunda es la lista de la que se van a quitar los números.The first list contains the numbers whose multiples will be removed, and the second list is the list from which to remove the numbers. El código del ejemplo siguiente usa esta función recursiva para eliminar de una lista todos los números que no sean primos, dejando como resultado una lista de números primos.The code in the following example uses this recursive function to eliminate all the non-prime numbers from a list, leaving a list of prime numbers as the result.
let IsPrimeMultipleTest n x =
x = n || x % n <> 0
let rec RemoveAllMultiples listn listx =
match listn with
| head :: tail -> RemoveAllMultiples tail (List.filter (IsPrimeMultipleTest head) listx)
| [] -> listx
let GetPrimesUpTo n =
let max = int (sqrt (float n))
RemoveAllMultiples [ 2 .. max ] [ 1 .. n ]
printfn "Primes Up To %d:\n %A" 100 (GetPrimesUpTo 100)
La salida es la siguiente:The output is as follows:
Primes Up To 100:
[2; 3; 5; 7; 11; 13; 17; 19; 23; 29; 31; 37; 41; 43; 47; 53; 59; 61; 67; 71; 73; 79; 83; 89; 97]
Funciones del móduloModule Functions
El módulo de lista proporciona funciones que tienen acceso a los elementos de una lista.The List module provides functions that access the elements of a list. El elemento de encabezado es la manera más rápida y sencilla de acceder.The head element is the fastest and easiest to access. Use el encabezado de propiedad o la función de módulo List. Head.Use the property Head or the module function List.head. Puede tener acceso al final de una lista mediante la propiedad tail o la función List. tail .You can access the tail of a list by using the Tail property or the List.tail function. Para buscar un elemento por índice, use la función List. nth .To find an element by index, use the List.nth function. List.nth
atraviesa la lista.List.nth
traverses the list. Por lo tanto, es O (n).Therefore, it is O(n). Si su código usa List.nth
con frecuencia, quizás quiera considerar la posibilidad de usar una matriz en lugar de una lista.If your code uses List.nth
frequently, you might want to consider using an array instead of a list. El acceso a elementos en las matrices es O(1).Element access in arrays is O(1).
Operaciones booleanas en listasBoolean Operations on Lists
La función List. IsEmpty determina si una lista tiene elementos.The List.isEmpty function determines whether a list has any elements.
La función List. exists aplica una prueba booleana a los elementos de una lista true
y devuelve si algún elemento cumple la prueba.The List.exists function applies a Boolean test to elements of a list and returns true
if any element satisfies the test. List. exists2 ( es similar pero funciona en pares sucesivos de elementos de dos listas.List.exists2 is similar but operates on successive pairs of elements in two lists.
En el código siguiente se muestra cómo usar List.exists
.The following code demonstrates the use of List.exists
.
// Use List.exists to determine whether there is an element of a list satisfies a given Boolean expression.
// containsNumber returns true if any of the elements of the supplied list match
// the supplied number.
let containsNumber number list = List.exists (fun elem -> elem = number) list
let list0to3 = [0 .. 3]
printfn "For list %A, contains zero is %b" list0to3 (containsNumber 0 list0to3)
La salida es la siguiente:The output is as follows:
For list [0; 1; 2; 3], contains zero is true
El siguiente ejemplo muestra el uso de List.exists2
.The following example demonstrates the use of List.exists2
.
// Use List.exists2 to compare elements in two lists.
// isEqualElement returns true if any elements at the same position in two supplied
// lists match.
let isEqualElement list1 list2 = List.exists2 (fun elem1 elem2 -> elem1 = elem2) list1 list2
let list1to5 = [ 1 .. 5 ]
let list5to1 = [ 5 .. -1 .. 1 ]
if (isEqualElement list1to5 list5to1) then
printfn "Lists %A and %A have at least one equal element at the same position." list1to5 list5to1
else
printfn "Lists %A and %A do not have an equal element at the same position." list1to5 list5to1
La salida es la siguiente:The output is as follows:
Lists [1; 2; 3; 4; 5] and [5; 4; 3; 2; 1] have at least one equal element at the same position.
Puede usar List. ForAll si desea comprobar si todos los elementos de una lista cumplen una condición.You can use List.forall if you want to test whether all the elements of a list meet a condition.
let isAllZeroes list = List.forall (fun elem -> elem = 0.0) list
printfn "%b" (isAllZeroes [0.0; 0.0])
printfn "%b" (isAllZeroes [0.0; 1.0])
La salida es la siguiente:The output is as follows:
true
false
De forma similar, List. forall2 ( determina si todos los elementos de las posiciones correspondientes de dos listas satisfacen una expresión booleana que implica cada par de elementos.Similarly, List.forall2 determines whether all elements in the corresponding positions in two lists satisfy a Boolean expression that involves each pair of elements.
let listEqual list1 list2 = List.forall2 (fun elem1 elem2 -> elem1 = elem2) list1 list2
printfn "%b" (listEqual [0; 1; 2] [0; 1; 2])
printfn "%b" (listEqual [0; 0; 0] [0; 1; 0])
La salida es la siguiente:The output is as follows:
true
false
Operaciones de ordenación en listasSort Operations on Lists
Las funciones List. Sort, List. sortByy List. sortWith ( ordenan las listas.The List.sort, List.sortBy, and List.sortWith functions sort lists. La función de ordenación determina cuál de estas tres funciones se usará.The sorting function determines which of these three functions to use. List.sort
usa una comparación genérica predeterminada.List.sort
uses default generic comparison. La comparación genérica usa operadores globales basados en la función de comparación genérica para comparar valores.Generic comparison uses global operators based on the generic compare function to compare values. Funciona de forma eficaz con una amplia variedad de tipos de elemento, como tipos numéricos simples, tuplas, registros, uniones discriminadas, listas, matrices y cualquier tipo que implemente System.IComparable
.It works efficiently with a wide variety of element types, such as simple numeric types, tuples, records, discriminated unions, lists, arrays, and any type that implements System.IComparable
. Para los tipos que implementan System.IComparable
, la comparación genérica usa la función System.IComparable.CompareTo()
.For types that implement System.IComparable
, generic comparison uses the System.IComparable.CompareTo()
function. La comparación genérica también trabaja con cadenas, pero usa una ordenación independiente de la referencia cultural.Generic comparison also works with strings, but uses a culture-independent sorting order. La comparación genérica no se debe usar en tipos no admitidos, como los tipos de función.Generic comparison should not be used on unsupported types, such as function types. Además, el rendimiento de la comparación genérica predeterminada es mejor para tipos estructurados pequeños; para los tipos estructurados mayores que deben compararse y ordenarse con frecuencia, considere la posibilidad de implementar System.IComparable
y de proporcionar una implementación eficaz del método System.IComparable.CompareTo()
.Also, the performance of the default generic comparison is best for small structured types; for larger structured types that need to be compared and sorted frequently, consider implementing System.IComparable
and providing an efficient implementation of the System.IComparable.CompareTo()
method.
List.sortBy
toma una función que devuelve un valor que se usa como criterio de ordenación, y List.sortWith
toma una función de comparación como argumento.List.sortBy
takes a function that returns a value that is used as the sort criterion, and List.sortWith
takes a comparison function as an argument. Estas dos últimas funciones son útiles cuando se trabaja con tipos que no permiten la comparación, o cuando la comparación requiere semánticas de comparación más complejas, como es el caso de las cadenas que tienen en cuenta la referencia cultural.These latter two functions are useful when you are working with types that do not support comparison, or when the comparison requires more complex comparison semantics, as in the case of culture-aware strings.
El siguiente ejemplo muestra el uso de List.sort
.The following example demonstrates the use of List.sort
.
let sortedList1 = List.sort [1; 4; 8; -2; 5]
printfn "%A" sortedList1
La salida es la siguiente:The output is as follows:
[-2; 1; 4; 5; 8]
El siguiente ejemplo muestra el uso de List.sortBy
.The following example demonstrates the use of List.sortBy
.
let sortedList2 = List.sortBy (fun elem -> abs elem) [1; 4; 8; -2; 5]
printfn "%A" sortedList2
La salida es la siguiente:The output is as follows:
[1; -2; 4; 5; 8]
El siguiente ejemplo muestra el uso de List.sortWith
.The next example demonstrates the use of List.sortWith
. En este ejemplo, la función de comparación personalizada compareWidgets
se usa para comparar primero un campo de un tipo personalizado, y después otro cuando los valores del primer campo son iguales.In this example, the custom comparison function compareWidgets
is used to first compare one field of a custom type, and then another when the values of the first field are equal.
type Widget = { ID: int; Rev: int }
let compareWidgets widget1 widget2 =
if widget1.ID < widget2.ID then -1 else
if widget1.ID > widget2.ID then 1 else
if widget1.Rev < widget2.Rev then -1 else
if widget1.Rev > widget2.Rev then 1 else
0
let listToCompare = [
{ ID = 92; Rev = 1 }
{ ID = 110; Rev = 1 }
{ ID = 100; Rev = 5 }
{ ID = 100; Rev = 2 }
{ ID = 92; Rev = 1 }
]
let sortedWidgetList = List.sortWith compareWidgets listToCompare
printfn "%A" sortedWidgetList
La salida es la siguiente:The output is as follows:
[{ID = 92;
Rev = 1;}; {ID = 92;
Rev = 1;}; {ID = 100;
Rev = 2;}; {ID = 100;
Rev = 5;}; {ID = 110;
Rev = 1;}]
Operaciones de búsqueda en listasSearch Operations on Lists
Se admiten numerosas operaciones de búsqueda en las listas.Numerous search operations are supported for lists. La más sencilla, List. Find, permite buscar el primer elemento que coincide con una condición determinada.The simplest, List.find, enables you to find the first element that matches a given condition.
El ejemplo de código siguiente muestra el uso de List.find
para buscar el primer número que es divisible por 5 en una lista.The following code example demonstrates the use of List.find
to find the first number that is divisible by 5 in a list.
let isDivisibleBy number elem = elem % number = 0
let result = List.find (isDivisibleBy 5) [ 1 .. 100 ]
printfn "%d " result
El resultado es 5.The result is 5.
Si los elementos se deben transformar primero, llame a List. Pick, que toma una función que devuelve una opción y busca el primer valor de opción que sea Some(x)
.If the elements must be transformed first, call List.pick, which takes a function that returns an option, and looks for the first option value that is Some(x)
. En lugar de devolver el elemento, List.pick
devuelve el resultado x
.Instead of returning the element, List.pick
returns the result x
. Si no se encuentra ningún elemento coincidente, List.pick
activa System.Collections.Generic.KeyNotFoundException
.If no matching element is found, List.pick
throws System.Collections.Generic.KeyNotFoundException
. En el código siguiente se muestra el uso de List.pick
.The following code shows the use of List.pick
.
let valuesList = [ ("a", 1); ("b", 2); ("c", 3) ]
let resultPick = List.pick (fun elem ->
match elem with
| (value, 2) -> Some value
| _ -> None) valuesList
printfn "%A" resultPick
La salida es la siguiente:The output is as follows:
"b"
Otro grupo de operaciones de búsqueda, List. tryFind y funciones relacionadas, devuelven un valor de opción.Another group of search operations, List.tryFind and related functions, return an option value. La función List.tryFind
devuelve el primer elemento de una lista que cumple una condición si ese elemento existe, pero el valor de opción None
si no.The List.tryFind
function returns the first element of a list that satisfies a condition if such an element exists, but the option value None
if not. La variación List. tryfindindex ( devuelve el índice del elemento, si se encuentra uno, en lugar del propio elemento.The variation List.tryFindIndex returns the index of the element, if one is found, rather than the element itself. Estas funciones quedan reflejadas en el código siguiente.These functions are illustrated in the following code.
let list1d = [1; 3; 7; 9; 11; 13; 15; 19; 22; 29; 36]
let isEven x = x % 2 = 0
match List.tryFind isEven list1d with
| Some value -> printfn "The first even value is %d." value
| None -> printfn "There is no even value in the list."
match List.tryFindIndex isEven list1d with
| Some value -> printfn "The first even value is at position %d." value
| None -> printfn "There is no even value in the list."
La salida es la siguiente:The output is as follows:
The first even value is 22.
The first even value is at position 8.
Operaciones aritméticas en listasArithmetic Operations on Lists
Las operaciones aritméticas comunes, como SUM y Average, se integran en el módulo List.Common arithmetic operations such as sum and average are built into the List module. Para trabajar con List. SUM, el tipo de elemento de lista debe +
admitir el operador y tener un valor de cero.To work with List.sum, the list element type must support the +
operator and have a zero value. Todos los tipos aritmético integrados cumplen estas condiciones.All built-in arithmetic types satisfy these conditions. Para trabajar con List. Average, el tipo de elemento debe admitir la división sin resto, lo que excluye los tipos enteros, pero permite tipos de punto flotante.To work with List.average, the element type must support division without a remainder, which excludes integral types but allows for floating point types. Las funciones List. sumBy ( y List. averageBy toman una función como parámetro, y los resultados de esta función se usan para calcular los valores de la suma o el promedio.The List.sumBy and List.averageBy functions take a function as a parameter, and this function's results are used to calculate the values for the sum or average.
En el código siguiente se muestra cómo usar List.sum
, List.sumBy
y List.average
.The following code demonstrates the use of List.sum
, List.sumBy
, and List.average
.
// Compute the sum of the first 10 integers by using List.sum.
let sum1 = List.sum [1 .. 10]
// Compute the sum of the squares of the elements of a list by using List.sumBy.
let sum2 = List.sumBy (fun elem -> elem*elem) [1 .. 10]
// Compute the average of the elements of a list by using List.average.
let avg1 = List.average [0.0; 1.0; 1.0; 2.0]
printfn "%f" avg1
El resultado es 1.000000
The output is 1.000000
.
En el código siguiente se muestra el uso de List.averageBy
.The following code shows the use of List.averageBy
.
let avg2 = List.averageBy (fun elem -> float elem) [1 .. 10]
printfn "%f" avg2
El resultado es 5.5
The output is 5.5
.
Listas y tuplasLists and Tuples
Las listas que contienen tuplas se pueden manipular con las funciones zip y unzip.Lists that contain tuples can be manipulated by zip and unzip functions. Estas funciones combinan dos listas de valores únicos en una lista de tuplas o separan una lista de tuplas en dos listas de valores únicos.These functions combine two lists of single values into one list of tuples or separate one list of tuples into two lists of single values. La función List. zip más sencilla toma dos listas de elementos únicos y genera una sola lista de pares de tupla.The simplest List.zip function takes two lists of single elements and produces a single list of tuple pairs. Otra versión, List. zip3 (, toma tres listas de elementos únicos y genera una única lista de tuplas que tienen tres elementos.Another version, List.zip3, takes three lists of single elements and produces a single list of tuples that have three elements. En el siguiente ejemplo de código se muestra el uso de List.zip
.The following code example demonstrates the use of List.zip
.
let list1 = [ 1; 2; 3 ]
let list2 = [ -1; -2; -3 ]
let listZip = List.zip list1 list2
printfn "%A" listZip
La salida es la siguiente:The output is as follows:
[(1, -1); (2, -2); (3; -3)]
En el siguiente ejemplo de código se muestra el uso de List.zip3
.The following code example demonstrates the use of List.zip3
.
let list3 = [ 0; 0; 0]
let listZip3 = List.zip3 list1 list2 list3
printfn "%A" listZip3
La salida es la siguiente:The output is as follows:
[(1, -1, 0); (2, -2, 0); (3, -3, 0)]
Las versiones de unzip correspondientes, List. unzip y List. unzip3 (, toman listas de tuplas y devuelven listas en una tupla, donde la primera lista contiene todos los elementos que estaban en primer lugar en cada tupla y la segunda lista contiene el segundo elemento de cada uno. tupla, etc.The corresponding unzip versions, List.unzip and List.unzip3, take lists of tuples and return lists in a tuple, where the first list contains all the elements that were first in each tuple, and the second list contains the second element of each tuple, and so on.
En el ejemplo de código siguiente se muestra el uso de List. unzip.The following code example demonstrates the use of List.unzip.
let lists = List.unzip [(1,2); (3,4)]
printfn "%A" lists
printfn "%A %A" (fst lists) (snd lists)
La salida es la siguiente:The output is as follows:
([1; 3], [2; 4])
[1; 3] [2; 4]
En el ejemplo de código siguiente se muestra el uso de List. unzip3 (.The following code example demonstrates the use of List.unzip3.
let listsUnzip3 = List.unzip3 [(1,2,3); (4,5,6)]
printfn "%A" listsUnzip3
La salida es la siguiente:The output is as follows:
([1; 4], [2; 5], [3; 6])
Operar en elementos de listaOperating on List Elements
F# admite diferentes operaciones en los elementos de lista.F# supports a variety of operations on list elements. La más sencilla es List. ITER, que le permite llamar a una función en cada elemento de una lista.The simplest is List.iter, which enables you to call a function on every element of a list. Las variaciones incluyen List. iter2 (, que permite realizar una operación en elementos de dos listas, List. ITERI, que es como List.iter
, a excepción de que el índice de cada elemento se pasa como argumento a la función a la que se llama para cada uno. Element y List. iteri2 (, que es una combinación de la funcionalidad de List.iter2
y. List.iteri
Variations include List.iter2, which enables you to perform an operation on elements of two lists, List.iteri, which is like List.iter
except that the index of each element is passed as an argument to the function that is called for each element, and List.iteri2, which is a combination of the functionality of List.iter2
and List.iteri
. En el siguiente ejemplo de código se muestran estas funciones.The following code example illustrates these functions.
let list1 = [1; 2; 3]
let list2 = [4; 5; 6]
List.iter (fun x -> printfn "List.iter: element is %d" x) list1
List.iteri(fun i x -> printfn "List.iteri: element %d is %d" i x) list1
List.iter2 (fun x y -> printfn "List.iter2: elements are %d %d" x y) list1 list2
List.iteri2 (fun i x y ->
printfn "List.iteri2: element %d of list1 is %d element %d of list2 is %d"
i x i y)
list1 list2
La salida es la siguiente:The output is as follows:
List.iter: element is 1
List.iter: element is 2
List.iter: element is 3
List.iteri: element 0 is 1
List.iteri: element 1 is 2
List.iteri: element 2 is 3
List.iter2: elements are 1 4
List.iter2: elements are 2 5
List.iter2: elements are 3 6
List.iteri2: element 0 of list1 is 1; element 0 of list2 is 4
List.iteri2: element 1 of list1 is 2; element 1 of list2 is 5
List.iteri2: element 2 of list1 is 3; element 2 of list2 is 6
Otra función que se usa con frecuencia que transforma elementos de lista es List. map, que permite aplicar una función a cada elemento de una lista y colocar todos los resultados en una nueva lista.Another frequently used function that transforms list elements is List.map, which enables you to apply a function to each element of a list and put all the results into a new list. List. MAP2 ( y List. map3 ( son variaciones que toman varias listas.List.map2 and List.map3 are variations that take multiple lists. También puede usar List. MAPI y List. mapi2 (si, además del elemento, la función debe pasar el índice de cada elemento.You can also use List.mapi and List.mapi2, if, in addition to the element, the function needs to be passed the index of each element. La única diferencia entre List.mapi2
y List.mapi
es que List.mapi2
trabaja con dos listas.The only difference between List.mapi2
and List.mapi
is that List.mapi2
works with two lists. En el ejemplo siguiente se muestra List. map.The following example illustrates List.map.
let list1 = [1; 2; 3]
let newList = List.map (fun x -> x + 1) list1
printfn "%A" newList
La salida es la siguiente:The output is as follows:
[2; 3; 4]
En el ejemplo siguiente se muestra el uso de List.map2
.The following example shows the use of List.map2
.
let list1 = [1; 2; 3]
let list2 = [4; 5; 6]
let sumList = List.map2 (fun x y -> x + y) list1 list2
printfn "%A" sumList
La salida es la siguiente:The output is as follows:
[5; 7; 9]
En el ejemplo siguiente se muestra el uso de List.map3
.The following example shows the use of List.map3
.
let newList2 = List.map3 (fun x y z -> x + y + z) list1 list2 [2; 3; 4]
printfn "%A" newList2
La salida es la siguiente:The output is as follows:
[7; 10; 13]
En el ejemplo siguiente se muestra el uso de List.mapi
.The following example shows the use of List.mapi
.
let newListAddIndex = List.mapi (fun i x -> x + i) list1
printfn "%A" newListAddIndex
La salida es la siguiente:The output is as follows:
[1; 3; 5]
En el ejemplo siguiente se muestra el uso de List.mapi2
.The following example shows the use of List.mapi2
.
let listAddTimesIndex = List.mapi2 (fun i x y -> (x + y) * i) list1 list2
printfn "%A" listAddTimesIndex
La salida es la siguiente:The output is as follows:
[0; 7; 18]
List. Collect es como List.map
, salvo que cada elemento genera una lista y todas estas listas se concatenan en una lista final.List.collect is like List.map
, except that each element produces a list and all these lists are concatenated into a final list. En el código siguiente, cada elemento de la lista genera tres números.In the following code, each element of the list generates three numbers. Todos ellos se recopilan en una lista.These are all collected into one list.
let collectList = List.collect (fun x -> [for i in 1..3 -> x * i]) list1
printfn "%A" collectList
La salida es la siguiente:The output is as follows:
[1; 2; 3; 2; 4; 6; 3; 6; 9]
También puede usar List. Filter, que toma una condición booleana y genera una nueva lista que solo consta de los elementos que satisfacen la condición especificada.You can also use List.filter, which takes a Boolean condition and produces a new list that consists only of elements that satisfy the given condition.
let evenOnlyList = List.filter (fun x -> x % 2 = 0) [1; 2; 3; 4; 5; 6]
La lista resultante es [2; 4; 6]
.The resulting list is [2; 4; 6]
.
Una combinación de asignación y filtro, List. Choose permite transformar y seleccionar elementos al mismo tiempo.A combination of map and filter, List.choose enables you to transform and select elements at the same time. List.choose
aplica una función que devuelve una opción a cada elemento de una lista, y devuelve una nueva lista de resultados de elementos cuando la función devuelve el valor de opción Some
.List.choose
applies a function that returns an option to each element of a list, and returns a new list of the results for elements when the function returns the option value Some
.
El código siguiente muestra cómo usar List.choose
para seleccionar las palabras en mayúsculas de una lista de palabras.The following code demonstrates the use of List.choose
to select capitalized words out of a list of words.
let listWords = [ "and"; "Rome"; "Bob"; "apple"; "zebra" ]
let isCapitalized (string1:string) = System.Char.IsUpper string1.[0]
let results = List.choose (fun elem ->
match elem with
| elem when isCapitalized elem -> Some(elem + "'s")
| _ -> None) listWords
printfn "%A" results
La salida es la siguiente:The output is as follows:
["Rome's"; "Bob's"]
Operar en varias listasOperating on Multiple Lists
Las listas se pueden unir entre sí.Lists can be joined together. Para combinar dos listas en una, use List. Append.To join two lists into one, use List.append. Para combinar más de dos listas, use List. concat.To join more than two lists, use List.concat.
let list1to10 = List.append [1; 2; 3] [4; 5; 6; 7; 8; 9; 10]
let listResult = List.concat [ [1; 2; 3]; [4; 5; 6]; [7; 8; 9] ]
List.iter (fun elem -> printf "%d " elem) list1to10
printfn ""
List.iter (fun elem -> printf "%d " elem) listResult
Operaciones de plegamiento y exploraciónFold and Scan Operations
Algunas operaciones de lista implican interdependencias entre todos los elementos de lista.Some list operations involve interdependencies between all of the list elements. Las operaciones de plegamiento y de recorrido List.iter
son List.map
como y, en el caso de que se invoque una función en cada elemento, pero estas operaciones proporcionan un parámetro adicional denominado el acumulador que lleva información a través del cálculo.The fold and scan operations are like List.iter
and List.map
in that you invoke a function on each element, but these operations provide an additional parameter called the accumulator that carries information through the computation.
Use List.fold
para realizar un cálculo en una lista.Use List.fold
to perform a calculation on a list.
En el ejemplo de código siguiente se muestra el uso de List. Fold para realizar varias operaciones.The following code example demonstrates the use of List.fold to perform various operations.
La lista se atraviesa; el acumulador acc
es un valor que va pasando mientras se realiza el cálculo.The list is traversed; the accumulator acc
is a value that is passed along as the calculation proceeds. El primer argumento toma el acumulador y el elemento de lista y devuelve el resultado provisional del cálculo para ese elemento de lista.The first argument takes the accumulator and the list element, and returns the interim result of the calculation for that list element. El segundo argumento es el valor inicial del acumulador.The second argument is the initial value of the accumulator.
let sumList list = List.fold (fun acc elem -> acc + elem) 0 list
printfn "Sum of the elements of list %A is %d." [ 1 .. 3 ] (sumList [ 1 .. 3 ])
// The following example computes the average of a list.
let averageList list = (List.fold (fun acc elem -> acc + float elem) 0.0 list / float list.Length)
// The following example computes the standard deviation of a list.
// The standard deviation is computed by taking the square root of the
// sum of the variances, which are the differences between each value
// and the average.
let stdDevList list =
let avg = averageList list
sqrt (List.fold (fun acc elem -> acc + (float elem - avg) ** 2.0 ) 0.0 list / float list.Length)
let testList listTest =
printfn "List %A average: %f stddev: %f" listTest (averageList listTest) (stdDevList listTest)
testList [1; 1; 1]
testList [1; 2; 1]
testList [1; 2; 3]
// List.fold is the same as to List.iter when the accumulator is not used.
let printList list = List.fold (fun acc elem -> printfn "%A" elem) () list
printList [0.0; 1.0; 2.5; 5.1 ]
// The following example uses List.fold to reverse a list.
// The accumulator starts out as the empty list, and the function uses the cons operator
// to add each successive element to the head of the accumulator list, resulting in a
// reversed form of the list.
let reverseList list = List.fold (fun acc elem -> elem::acc) [] list
printfn "%A" (reverseList [1 .. 10])
Las versiones de estas funciones que tienen un dígito en el nombre de la función operan en más de una lista.The versions of these functions that have a digit in the function name operate on more than one list. Por ejemplo, List. fold2 ( realiza cálculos en dos listas.For example, List.fold2 performs computations on two lists.
El siguiente ejemplo muestra el uso de List.fold2
.The following example demonstrates the use of List.fold2
.
// Use List.fold2 to perform computations over two lists (of equal size) at the same time.
// Example: Sum the greater element at each list position.
let sumGreatest list1 list2 = List.fold2 (fun acc elem1 elem2 ->
acc + max elem1 elem2) 0 list1 list2
let sum = sumGreatest [1; 2; 3] [3; 2; 1]
printfn "The sum of the greater of each pair of elements in the two lists is %d." sum
List.fold
y List. Scan difiere en List.fold
que devuelve el valor final del parámetro adicional, pero List.scan
devuelve la lista de los valores intermedios (junto con el valor final) del parámetro adicional.List.fold
and List.scan differ in that List.fold
returns the final value of the extra parameter, but List.scan
returns the list of the intermediate values (along with the final value) of the extra parameter.
Cada una de estas funciones incluye una variación inversa, por ejemplo, List. foldBack, que difiere en el orden en el que se recorre la lista y el orden de los argumentos.Each of these functions includes a reverse variation, for example, List.foldBack, which differs in the order in which the list is traversed and the order of the arguments. Además, List.fold
y List.foldBack
tienen variaciones, List. fold2 ( y List. foldBack2 (, que toman dos listas de la misma longitud.Also, List.fold
and List.foldBack
have variations, List.fold2 and List.foldBack2, that take two lists of equal length. La función que se ejecuta en cada elemento puede usar los elementos correspondientes de ambas listas para realizar alguna acción.The function that executes on each element can use corresponding elements of both lists to perform some action. Los tipos de elemento de las dos listas pueden ser diferentes, como en el ejemplo siguiente, en el que una lista contiene los importes de las transacciones de una cuenta bancaria y la otra lista contiene el tipo de transacción: ingreso o retirada.The element types of the two lists can be different, as in the following example, in which one list contains transaction amounts for a bank account, and the other list contains the type of transaction: deposit or withdrawal.
// Discriminated union type that encodes the transaction type.
type Transaction =
| Deposit
| Withdrawal
let transactionTypes = [Deposit; Deposit; Withdrawal]
let transactionAmounts = [100.00; 1000.00; 95.00 ]
let initialBalance = 200.00
// Use fold2 to perform a calculation on the list to update the account balance.
let endingBalance = List.fold2 (fun acc elem1 elem2 ->
match elem1 with
| Deposit -> acc + elem2
| Withdrawal -> acc - elem2)
initialBalance
transactionTypes
transactionAmounts
printfn "%f" endingBalance
Para un cálculo como la suma, List.fold
y List.foldBack
tiene el mismo efecto porque el resultado no depende del orden del recorrido.For a calculation like summation, List.fold
and List.foldBack
have the same effect because the result does not depend on the order of traversal. En el ejemplo siguientes, se usa List.foldBack
para sumar los elementos de una lista.In the following example, List.foldBack
is used to add the elements in a list.
let sumListBack list = List.foldBack (fun acc elem -> acc + elem) list 0
printfn "%d" (sumListBack [1; 2; 3])
// For a calculation in which the order of traversal is important, fold and foldBack have different
// results. For example, replacing fold with foldBack in the listReverse function
// produces a function that copies the list, rather than reversing it.
let copyList list = List.foldBack (fun elem acc -> elem::acc) list []
printfn "%A" (copyList [1 .. 10])
El ejemplo siguiente vuelve al ejemplo de la cuenta bancaria.The following example returns to the bank account example. Esta vez se agrega un nuevo tipo de transacción: un cálculo de interés.This time a new transaction type is added: an interest calculation. El saldo final depende ahora del orden de las transacciones.The ending balance now depends on the order of transactions.
type Transaction2 =
| Deposit
| Withdrawal
| Interest
let transactionTypes2 = [Deposit; Deposit; Withdrawal; Interest]
let transactionAmounts2 = [100.00; 1000.00; 95.00; 0.05 / 12.0 ]
let initialBalance2 = 200.00
// Because fold2 processes the lists by starting at the head element,
// the interest is calculated last, on the balance of 1205.00.
let endingBalance2 = List.fold2 (fun acc elem1 elem2 ->
match elem1 with
| Deposit -> acc + elem2
| Withdrawal -> acc - elem2
| Interest -> acc * (1.0 + elem2))
initialBalance2
transactionTypes2
transactionAmounts2
printfn "%f" endingBalance2
// Because foldBack2 processes the lists by starting at end of the list,
// the interest is calculated first, on the balance of only 200.00.
let endingBalance3 = List.foldBack2 (fun elem1 elem2 acc ->
match elem1 with
| Deposit -> acc + elem2
| Withdrawal -> acc - elem2
| Interest -> acc * (1.0 + elem2))
transactionTypes2
transactionAmounts2
initialBalance2
printfn "%f" endingBalance3
La lista de funciones . reduce es algo List.fold
parecido List.scan
a y, salvo que, en lugar de pasar un acumulador independiente, List.reduce
toma una función que toma dos argumentos del tipo de elemento en lugar de uno solo y uno de ellos. los argumentos actúan como el acumulador, lo que significa que almacena el resultado intermedio del cálculo.The function List.reduce is somewhat like List.fold
and List.scan
, except that instead of passing around a separate accumulator, List.reduce
takes a function that takes two arguments of the element type instead of just one, and one of those arguments acts as the accumulator, meaning that it stores the intermediate result of the computation. List.reduce
comienza por operar en los dos primeros elementos y, después, usa el resultado de la operación con el siguiente elemento.List.reduce
starts by operating on the first two list elements, and then uses the result of the operation along with the next element. Como no hay un acumulador diferente que tenga su propio tipo, se puede usar List.reduce
en lugar de List.fold
solo cuando el acumulador y el elemento sean del mismo tipo.Because there is not a separate accumulator that has its own type, List.reduce
can be used in place of List.fold
only when the accumulator and the element type have the same type. En el código siguiente se muestra cómo usar List.reduce
.The following code demonstrates the use of List.reduce
. List.reduce
activa una excepción si la lista proporciona no tiene elementos.List.reduce
throws an exception if the list provided has no elements.
En el código siguiente, en la primera llamada a la expresión lambda se proporcionan los argumentos 2 y 4, y devuelve 6; en la siguiente llamada se proporcionan los argumentos 6 y 10, por lo que el resultado es 16.In the following code, the first call to the lambda expression is given the arguments 2 and 4, and returns 6, and the next call is given the arguments 6 and 10, so the result is 16.
let sumAList list =
try
List.reduce (fun acc elem -> acc + elem) list
with
| :? System.ArgumentException as exc -> 0
let resultSum = sumAList [2; 4; 10]
printfn "%d " resultSum
Convertir entre listas y otros tipos de coleccionesConverting Between Lists and Other Collection Types
El módulo List
proporciona funciones para convertir desde y hacia secuencias y matrices.The List
module provides functions for converting to and from both sequences and arrays. Para convertir a o desde una secuencia, use List. toseq ( o List. ofSeq.To convert to or from a sequence, use List.toSeq or List.ofSeq. Para realizar la conversión a o desde una matriz, use List. toArray o List. myArray.To convert to or from an array, use List.toArray or List.ofArray.
Otras operacionesAdditional Operations
Para obtener información sobre las operaciones adicionales de las listas, vea el módulo de referencia de la biblioteca Collections. List.For information about additional operations on lists, see the library reference topic Collections.List Module.
Vea tambiénSee also
Comentarios
Cargando comentarios...