Un list es una colección mutable de elementos en secuencia.
Como la mayoría de las colecciones (consulta los tipos integrados tuple, dict y set), los arrays pueden contener referencias a cualquier tipo de dato (o a varios), incluidos otros arrays.
Como en cualquier secuencia, se puede acceder a los elementos mediante un 0-based index desde la izquierda y un -1-based index desde la derecha.
Los arrays se pueden copiar total o parcialmente mediante la notación de rebanadas o <list>.copy().
Los arrays admiten tanto operaciones de secuencia comunes como mutables, por ejemplo min()/max(), <list>.index(), <list>.append() y <list>.reverse().
Se puede iterar sobre los elementos de un array con la construcción for item in <list>.
La construcción for index, item in enumerate(<list>) se puede usar cuando se necesitan tanto el índice como el valor del elemento.
Internamente, los lists se implementan como arrays dinámicos, similares al tipo ArrayList de Java, y se suelen usar para almacenar grupos de datos similares (strings, números, conjuntos, etc.) de longitud desconocida.
Los arrays son una estructura de datos extremadamente flexible y útil, y muchos métodos y operaciones integrados de Python producen arrays como resultado.
Un list se puede declarar como un literal con corchetes [] y comas entre los elementos:
>>> no_elements = []
>>> no_elements
[]
>>> one_element = ["Guava"]
>>> one_element
['Guava']
>>> elements_separated_with_commas = ["Parrot", "Bird", 334782]
>>> elements_separated_with_commas
['Parrot', 'Bird', 334782]
Para mejorar la legibilidad, se pueden usar saltos de línea cuando hay muchos elementos o estructuras de datos anidadas dentro de un list:
>>> lots_of_entries = [
"Rose",
"Sunflower",
"Poppy",
"Pansy",
"Tulip",
"Fuchsia",
"Cyclamen",
"Lavender"
]
>>> lots_of_entries
['Rose', 'Sunflower', 'Poppy', 'Pansy', 'Tulip', 'Fuchsia', 'Cyclamen', 'Lavender']
# Each data structure is on its own line to help clarify what they are.
>>> nested_data_structures = [
{"fish": "gold", "monkey": "brown", "parrot": "grey"},
("fish", "mammal", "bird"),
['water', 'jungle', 'sky']
]
>>> nested_data_structures
[{'fish': 'gold', 'monkey': 'brown', 'parrot': 'grey'}, ('fish', 'mammal', 'bird'), ['water', 'jungle', 'sky']]
El constructor list() se puede usar vacío o con un iterable como argumento.
El constructor recorre los elementos del iterable y los añade al list en orden:
>>> no_elements = list()
>>> no_elements
[]
# The tuple is unpacked and each element is added.
>>> multiple_elements_from_tuple = list(("Parrot", "Bird", 334782))
>>> multiple_elements_from_tuple
['Parrot', 'Bird', 334782]
# The set is unpacked and each element is added.
>>> multiple_elements_from_set = list({2, 3, 5, 7, 11})
>>> multiple_elements_from_set
[2, 3, 5, 7, 11]
Los resultados de usar el constructor list con un string o un dict pueden sorprender:
# String elements (Unicode code points) are iterated through and added *individually*.
>>> multiple_elements_string = list("Timbuktu")
>>> multiple_elements_string
['T', 'i', 'm', 'b', 'u', 'k', 't', 'u']
# Unicode separators and positioning code points are also added *individually*.
>>> multiple_code_points_string = list('अभ्यास')
>>> multiple_code_points_string
['अ', 'भ', '्', 'य', 'ा', 'स']
# The iteration default for dictionaries is over the keys, so only key data is inserted into the list.
>>> source_data = {"fish": "gold", "monkey": "brown"}
>>> multiple_elements_dict_1 = list(source_data)
['fish', 'monkey']
Como el constructor list solo acepta iterables (o nada) como argumentos, los objetos que no son iterables lanzarán un error de tipo.
Por ello, es mucho más fácil crear un list de un solo elemento con el método literal.
# Numbers are not iterable, and so attempting to create a list with a number passed to the constructor fails.
>>> one_element = list(16)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'int' object is not iterable
# Tuples *are* iterable, so passing a one-element tuple to the constructor does work, but it's awkward
>>> one_element_from_iterable = list((16,))
>>> one_element_from_iterable
[16]
Se puede acceder a los elementos de un array (así como a los elementos de otros tipos de secuencia str y tuple) mediante un 0-based index y la notación de corchetes.
Los índices pueden ir de left --> right (empezando en cero) o de right --> left (empezando en -1).
| índice desde la izquierda ⟹ |
|
⟸ índice desde la derecha |
>>> breakfast_foods = ["Oatmeal", "Fruit Salad", "Eggs", "Toast"]
# Oatmeal is at index 0 or index -4.
>>> breakfast_foods[0]
'Oatmeal'
>>> breakfast_foods[-4]
'Oatmeal'
# Eggs are at index -2 or 2
>>> breakfast_foods[-2]
'Eggs'
>>> breakfast_foods[2]
'Eggs'
# Toast is at -1
>>> breakfast_foods[-1]
'Toast'
Se puede acceder a una sección de los elementos dentro de un list mediante la notación de rebanadas (<list>[start:stop]).
Una rebanada se define como una secuencia de elementos en la posición index, tal que start <= index < stop.
El slicing devuelve una copia de los elementos «rebanados» y no modifica el list original.
También se puede usar un parámetro step [start:stop:step] para «saltarse» o filtrar los elementos de un list (por ejemplo, un step de 2 seleccionará uno de cada dos elementos del rango):
>>> colors = ["Red", "Purple", "Green", "Yellow", "Orange", "Pink", "Blue", "Grey"]
# If there is no step parameter, the step is assumed to be 1.
>>> middle_colors = colors[2:6]
>>> middle_colors
['Green', 'Yellow', 'Orange', 'Pink']
# If the start or stop parameters are omitted, the slice will
# start at index zero, and will stop at the end of the list.
>>> primary_colors = colors[::3]
>>> primary_colors
['Red', 'Yellow', 'Blue']
Si se usa la función integrada sum() con un array, devuelve la suma de todos los números del array:
>>> number_list = [1, 2, 3, 4]
>>> sum(number_list)
10
También puedes obtener la longitud de un array con la función len():
>>> long_list = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J"]
>>> len(long_list)
10
Los arrays también se pueden combinar de varias formas:
# Using the plus + operator unpacks each list and creates a new list, but it is not efficient.
>>> new_via_concatenate = ["George", 5] + ["cat", "Tabby"]
>>> new_via_concatenate
['George', 5, 'cat', 'Tabby']
# Likewise, using the multiplication operator * is the equivalent of using + n times.
>>> first_group = ["cat", "dog", "elephant"]
>>> multiplied_group = first_group * 3
>>> multiplied_group
['cat', 'dog', 'elephant', 'cat', 'dog', 'elephant', 'cat', 'dog', 'elephant']
Los arrays proporcionan un iterador y se pueden recorrer con un bucle igual que otros tipos de secuencia.
# Looping through the list and printing out each element.
>>> colors = ["Orange", "Green", "Grey", "Blue"]
>>> for item in colors:
... print(item)
...
Orange
Green
Grey
Blue
Para obtener una explicación más detallada de los loops y los iterators, completa el concepto loops.
Elyse tiene muchas ganas de jugar al póker (y a otros juegos de cartas) durante su próximo viaje a Las Vegas. Como es una gran fanática del «autoseguimiento», quiere crear unas cuantas funciones pequeñas que la ayuden con las tareas de seguimiento y te ha pedido ayuda para pensarlas bien.
A Elyse le gusta el póker especialmente, y quiere llevar un registro de cuántas rondas juega, y de cuáles son esas rondas. Cada ronda tiene su propio número, y cada mesa muestra el número de la ronda que se está jugando en ese momento. Elyse elige una mesa y se sienta a jugar su primera ronda. Tiene pensado jugar tres rondas.
Implementa una función get_rounds(<round_number>) que reciba el número de la ronda actual y devuelva un único list con esa ronda y las dos siguientes que están por venir:
>>> get_rounds(27)
[27, 28, 29]
Elyse jugó unas cuantas rondas en la primera mesa, luego se tomó un descanso y jugó algunas rondas más en una segunda mesa... ¡pero acabó con un array distinto para cada mesa! Quiere juntar los dos arrays para poder llevar un registro de todas las rondas de póker en el mismo sitio.
Implementa una función concatenate_rounds(<rounds_1>, <rounds_2>) que reciba dos arrays y devuelva un único list formado por todas las rondas del primer list, seguidas de todas las rondas del segundo list:
>>> concatenate_rounds([27, 28, 29], [35, 36])
[27, 28, 29, 35, 36]
Hablando de algunas de las rondas anteriores de póker, otro jugador comenta lo parecidas que fueron dos de ellas. Elyse no está segura de si jugó esas rondas o no.
Implementa una función list_contains_round(<rounds>, <round_number>) que reciba dos argumentos: un array con las rondas jugadas y un número de ronda.
La función devolverá True si la ronda está en el array de rondas jugadas, y False si no:
>>> list_contains_round([27, 28, 29, 35, 36], 29)
True
>>> list_contains_round([27, 28, 29, 35, 36], 30)
False
Elyse quiere probar un juego nuevo llamado Black Joe. Es parecido al Black Jack, donde el objetivo es que las cartas de tu mano sumen un valor concreto, pero en Black Joe el objetivo es que la media de los valores de las cartas sea 7. La media se puede calcular sumando todos los valores de las cartas y dividiendo esa suma entre el número de cartas de la mano.
Implementa una función card_average(<hand>) que devuelva el valor medio de una mano de Black Joe.
>>> card_average([5, 6, 7])
6.0
En Black Joe, la velocidad es importante. Elyse va a intentar encontrar una forma más rápida de calcular la media.
Se le han ocurrido dos formas de obtener un número parecido a la media:
Implementa la función approx_average_is_average(<hand>), donde hand es un array que contiene los valores de las cartas de tu mano.
Devuelve True si una or ambas de las estrategias mencionadas anteriormente dan como resultado un número igual a la media real.
Nota: la longitud de todas las manos es impar, para que sea más fácil encontrar la mediana.
>>> approx_average_is_average([1, 2, 3])
True
>>> approx_average_is_average([2, 3, 4, 8, 8])
True
>>> approx_average_is_average([1, 2, 3, 5, 9])
False
Intrigada por los resultados de su experimento con las medias, Elyse se pregunta si calcular la media de las cartas en las posiciones pares frente a la media de las cartas en las posiciones impares daría los mismos resultados. ¡Es hora de otra función de prueba!
Implementa una función average_even_is_average_odd(<hand>) que devuelva un Boolean que indique si la media de las cartas en los índices pares es la misma que la media de las cartas en los índices impares.
>>> average_even_is_average_odd([1, 2, 3])
True
>>> average_even_is_average_odd([1, 2, 3, 4])
False
Cada 11.ª mano en Black Joe es una mano de bonificación con una regla de bonificación: si la última carta que robas es un Jack, duplicas su valor.
Implementa una función maybe_double_last(<hand>) que reciba una mano y compruebe si la última carta es un Jack (11).
Si la última carta es un Jack (11), duplica su valor antes de devolver la mano.
>>> hand = [5, 9, 11]
>>> maybe_double_last(hand)
[5, 9, 22]
>>> hand = [5, 9, 10]
>>> maybe_double_last(hand)
[5, 9, 10]
Regístrate en Exercism para aprender y dominar Python con 17 conceptos146 ejercicios y mentoría humana real, todo gratis.