<jupyter_start><jupyter_text>IWI131 Programación  Listas Una lista es una colección **ordenada** de elementos de cualquier tipo, incluso otras listas.Sus elementos individuales pueden accederse a través de **índices**, como con los caracteres de un string. De igual forma, se pueden extraer sublistas utilizando rebanadas.  Creación de Listas- Usando corchetes: `[]`- Usando el constructor: `list()`  Lista vacía<jupyter_code>a = []
b = list()
print(a)
print(b)<jupyter_output>[]
[]<jupyter_text>Lista con elementos<jupyter_code>a = [1,2,3,4]
palabra = "hola"
b = list([palabra,2,[1,2],'3'])
print(a)
print(b)

c = list("abc")
print(c)<jupyter_output>[1, 2, 3, 4]
['hola', 2, [1, 2], '3']
['a', 'b', 'c']<jupyter_text>Rangos La función `range` genera una secuencia **ordenada** de números enteros. En conjunto con el constructor `list()` permite crear una lista con la secuencia generada. `range(inicio,fin)` genera una secuencia ordenada de números enteros ordenados desde $inicio$ hasta $fin-1$.Si se omite el $inicio$, la secuencia va desde $0$ hasta $fin-1$.Aplicando `list()` construimos una lista con el rango correspondiente.<jupyter_code>a = list(range(4,10))
b = list(range(5))
print(a)
print(b)<jupyter_output>[4, 5, 6, 7, 8, 9]
[0, 1, 2, 3, 4]<jupyter_text>`range(inicio, fin, salto)` genera una secuencia ordenada de números enteros, desde $inicio$ hasta $fin-1$, saltando $salto$ entre cada par de números.<jupyter_code>c = list(range(2,10,3))
print(c)<jupyter_output>[2, 5, 8]<jupyter_text>Índices Las listas tienen índices para enumerar sus elementos, de manera similar que con strings.<jupyter_code>a = [1,2,3,4]
print(a[1])
print(a[10])<jupyter_output><empty_output><jupyter_text>Las listas también poseen índices negativos.<jupyter_code>a = [1,2,3,4]
#imprime por pantalla el penultimo elemento de la lista
print(a[-2])<jupyter_output>3<jupyter_text>La notación `l[inicio:fin]`, para extraer una rebanada, también es válida para listas.<jupyter_code>a = list(range(2,20))
print(a[4:15])<jupyter_output>[6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]<jupyter_text>Mutabilidad **A diferencia de los strings**, las listas son **mutables**, es decir, sus elementos **pueden cambiar**. El **índice** puede ser usado para **modificar** un elemento de la lista.<jupyter_code>colores = ["azul", "rojo", "verde", "amarillo"]
print("Lista antes de modificar un elemento por el indice")
print(colores)
colores[0] = "fucsia"
print("Lista despues de modificar un elemento por el indice")
print(colores)<jupyter_output>Lista antes de modificar un elemento por el indice
['azul', 'rojo', 'verde', 'amarillo']
Lista despues de modificar un elemento por el indice
['fucsia', 'rojo', 'verde', 'amarillo']<jupyter_text>Operaciones sobre listas Algunas operaciones de listas son análogas a las operaciones de strings:- Concatenación de lista (`+`)- Repetición de listas (`*`)- Verificar si un *elemento* está en en la lista- Eliminar el elemento i-ésimo de una lista  Concatenación de listasEl operador suma (`+`) crea una **nueva lista** como la **concatenación de las dos listas utilizadas** como operandos.<jupyter_code>a = [1,2,3]
b = [4,6,8]
c = a + b
d = b + a
print(c)
print(d)
[1,2] + [2,6]<jupyter_output><empty_output><jupyter_text>Repetición de listasEl operador multiplicación (`*`) crea una **nueva lista** como **la repetición de la lista** que aparece como operando, la cantidad de veces indicada.<jupyter_code>a = [1,4,6]
c = a*3
print(c)<jupyter_output>[1, 4, 6, 1, 4, 6, 1, 4, 6]<jupyter_text>Verificar si elemento se encuentra en la listaLa instrucción `in` permite verificar si un elemento está contenido en la lista.<jupyter_code>a = [1,2,3,4]
print(3 in a)<jupyter_output>True<jupyter_text>Eliminar un elemento de la lista- Utilizando la instrucción `del`, es posible eliminar un elemento de la lista.- Se debe indicar el **índice del elemento** de la lista a eliminar.<jupyter_code>a = [1,2,3,4,2]
print("lista antes de eliminar el elemento a[-3]")
print(a)
del a[-3]
print("lista despues de eliminar a[-3]")
print(a)<jupyter_output>lista antes de eliminar el elemento a[-3]
[1, 2, 3, 4, 2]
lista despues de eliminar a[-3]
[1, 2, 4, 2]<jupyter_text>Funciones que aceptan listas como parámetros  Longitud de una listaLa función `len(lista)` entrega la cantidad de elementos de la lista ingresada como parámetro.<jupyter_code>a = [1,2,3,4]
c = len(a)
print("La cantidad de elementos de la lista es",c)
b = [[1,2,3,4]]
d = len(b[0])
print("La cantidad de elementos de la lista es",d)<jupyter_output>La cantidad de elementos de la lista es 4<jupyter_text>¿Qué ocurre con la cantidad de elementos de las listas vacías?<jupyter_code>print(len([]))
print(len(list()))<jupyter_output>0<jupyter_text>Suma de los valores de una listaUsando la función `sum(lista)`, se puede determinar la suma de los elementos de una lista.<jupyter_code>sum([1,5,3])
sum([1.0,5.4,3])<jupyter_output><empty_output><jupyter_text>¿Que hace el siguiente programa?<jupyter_code>b = 5
a = [1,2,4,b]
c = sum(a)/len(a)
print(round(c))<jupyter_output>3<jupyter_text>Mínimo en una lista de elementosLa función `min(lista)` entrega el valor mínimo en la `lista` ingresada como parámetro.<jupyter_code>m = min([1,6,2,-1])
print(m)<jupyter_output>-1<jupyter_text>Máximo en una lista de elementosLa función `max(lista)` entrega el valor máximo en la `lista` ingresada como parámetro.<jupyter_code>m = max([1,6,2,-1])
print(m)<jupyter_output>6<jupyter_text>Métodos para listas - Agregar un elemento `x`: `l.append(x)`- Agregar un elemento `x` en una posición `pos`: `l.insert(pos,x)`- Contar la cantidad de ocurrencias de un elemento `x`: `l.count(x)`- Obtener el índice de un elemento `x`: `l.index(x)`- Eliminar un elemento `x`: `l.remove(x)`- Invertir una lista: `l.reverse()`- Ordenar una lista: `l.sort()` **Importante:** recordar que los métodos operan sobre una lista implícita, indicada **antes** del punto.  Agregar un elemento- Usando `append`, se agregará un elemento al final de la lista.<jupyter_code>a = [1,2,3,4]
print("lista antes de agregar un elemento")
print(a)
#agregar un 4 al final de la lista
a.append(4)
print("lista despues de agregar un elemento")
print(a)<jupyter_output>lista antes de agregar un elemento
[1, 2, 3, 4]
lista despues de agregar un elemento
[1, 2, 3, 4, 4]<jupyter_text>Agregar un elemento en una posiciónUsando el método `insert` se puede agregar un elemento en la lista en la posición i-ésima ingresada como parámetro.<jupyter_code>a = [1,2,3,4]
print("lista antes de agregar un elemento")
print(a)
#agregar un 10 en a[2]
a.insert(2,10)
print("lista despues de agregar un elemento")
print(a)<jupyter_output>lista antes de agregar un elemento
[1, 2, 3, 4]
lista despues de agregar un elemento
[1, 2, 10, 3, 4]<jupyter_text>Contar la aparición de un elemento en una listaEl método `count` cuenta cuántas veces aparece un elemento en la lista.<jupyter_code>a = list("paralelepipedo")
b = a.count("p")
print(b)<jupyter_output>3<jupyter_text>Índice de un elemento- El método `index` entrega la posición de un elemento en la lista.- Si hay más de un elemento en la lista, entrega la posición del primer elemento (sentido izquierda - derecha).- El elemento debe existir.<jupyter_code>a = [1,2,3,4,3]
a.index(3)
a.index(214)<jupyter_output><empty_output><jupyter_text>¿Cómo se puede asegurar que al usar `index` no habrá error?<jupyter_code>a = [1,2,3,4,3]
if 214 in a:
    print("El elemento 214 esta en el indice",a.index(214))
    
if 3 in a:
    print("El elemento 3 esta en el indice",a.index(3))<jupyter_output>El elemento 3 esta en el indice 2<jupyter_text>Eliminar un elemento de una lista- El método `remove` elimina el elemento ingresado como parámetro.- Si hay más de un elemento en la lista, elimina el primer elemento (sentido izquierda - derecha).- El elemento debe existir en la lista.<jupyter_code>a = [1,2,3,5,3]
print("lista antes de eliminar el elemento 3")
print(a)
#eliminar el elemento 3 de la lista
a.remove(3)
print("lista despues de eliminar")
print(a)
a.remove(7)<jupyter_output><empty_output><jupyter_text>¿Cómo se puede evitar este error al intentar eliminar un elemento?<jupyter_code>a = [1,2,3,5,3]
if 7 in a:
    a.remove(7)<jupyter_output><empty_output><jupyter_text>Invertir una listaEl método `reverse` invierte el orden de los elementos de una lista.<jupyter_code>a = [4,1,10,5]
print("lista antes de invertir")
print(a)
a.reverse()
print("lista despues de invertir")
print(a)<jupyter_output>lista antes de invertir
[4, 1, 10, 5]
lista despues de invertir
[5, 10, 1, 4]<jupyter_text>Ordenar una listaEl método `sort` ordena los elementos de una lista en orden creciente.<jupyter_code>a = [4,1,10,6]
print("lista antes de ordenar")
print(a)
a.sort()
print("lista despues de ordenar")
print(a)<jupyter_output>lista antes de ordenar
[4, 1, 10, 6]
lista despues de ordenar
[1, 4, 6, 10]<jupyter_text>¿Cómo ordenar los elementos de una lista en orden decreciente?<jupyter_code>a = [4,1,10,6]
print("lista antes de ordenar")
print(a)
a.sort()
a.reverse()
print("lista despues de ordenar")
print(a)<jupyter_output>lista antes de ordenar
[4, 1, 10, 6]
lista despues de ordenar
[10, 6, 4, 1]<jupyter_text>Ciclo `for` en listas- Un ciclo `for` puede ser usado para iterar sobre listas.<jupyter_code>lista = [1,4,"s",[1,5]]
for elem in lista:
    print("elem =",elem)<jupyter_output>elem = 1
elem = 4
elem = s
elem = [1, 5]<jupyter_text>Utilizando `range` en un ciclo `for`<jupyter_code>suma = 0
for k in range(3,6):
    suma += k**2
print(suma)
for i in range(5):
    print("hola persona "+str(i+1))
for i in range(2,5):
    print(i)<jupyter_output>2
3
4<jupyter_text>Equivalencia entre ciclo `while` y ciclo `for`¿Son equivalentes los siguientes códigos?<jupyter_code>contador = 0
suma = 0
while contador < 5:
    suma += contador
    contador += 1
print("La suma es igual a",suma)
suma = 0
for contador in range(5):
    suma += contador
print("La suma es igual a",suma)<jupyter_output>La suma es igual a 10<jupyter_text>Iteración de listas usando ciclo `while` y ciclo `for`<jupyter_code>ramos = ["Progra", "Mate", "Fisica"]
i = 0
while i < len(ramos):
    print("Tengo clases de",ramos[i])
    i += 1
ramos = ["Progra", "Mate", "Fisica"]
for ramo in ramos:
    print("Tengo clases de",ramo)
ramos = ["Progra", "Mate", "Fisica"]
horas = ["8:00", "10:00", "12:00"]
i = 0
while i < len(ramos):
    print("Tengo clases de",ramos[i],"a las", horas[i])
    i += 1
ramos = ["Progra", "Mate", "Fisica"]
horas = ["8:00", "10:00", "12:00"]
print(list(range(len(ramos))))
for i in range(len(ramos)):
    print("Tengo clases de",ramos[i],"a las", horas[i])<jupyter_output>[0, 1, 2]
Tengo clases de Progra a las 8:00
Tengo clases de Mate a las 10:00
Tengo clases de Fisica a las 12:00<jupyter_text>Listas Bi-dimensionales * Las listas bi-dimensionales se caracterizan por que **al menos** un elemento de la lista es,  a su vez, otra lista.* Tambien se les llama: **listas de listas** o **listas anidadas**.* Las listas de listas tienen las mismas caractersiticas que una lista normal (o uni-dimensional). Es decir:    1. Se les puede aplicar los métodos ya vistos: `.append()`, `.sort()`, `.remove()`, etc.         2. Estas listas pueden tener cualquier tamaño, incluso pueden crearse como listas vacias.    3. Pueden contener cualquier tipo de dato.  Ejemplo de listas de listas pueden ser:<jupyter_code>L1 = [1,2,3, [4,5,6,7,8], 9]
L2 = [True, 234, [1988, 4, 12], 'lista de listas', [False, '789']]
L3 = [[],[]]
print('Lista L1:', L1)
print('Lista L2:', L2)
print('Lista L3:', L3)<jupyter_output>Lista L1: [1, 2, 3, [4, 5, 6, 7, 8], 9]
Lista L2: [True, 234, [1988, 4, 12], 'lista de listas', [False, '789']]
Lista L3: [[], []]<jupyter_text>Se debe tener conciencia que en estos casos, los elementos de las listas pueden ser elementos que pueden contener a su vez otros elementos.  **Ejemplo:** Los elementos de la lista `L1` son 5: `1, 2, 3, [4, 5, 6, 7, 8], 9`. Entonces, el cuarto elemento, es decir el elemento con el **índice 3**, es: `[4, 5, 6, 7, 8]`.<jupyter_code>print(L1[3])
print(L1[-1])<jupyter_output>9<jupyter_text>Entonces, teniendo las listas `L1`, `L2`, y `L3`<jupyter_code>print('Lista L1:', L1)
print('Lista L2:', L2)
print('Lista L3:', L3)<jupyter_output>Lista L1: [1, 2, 3, [4, 5, 6, 7, 8], 9]
Lista L2: [True, 234, [1988, 4, 12], 'lista de listas', [False, '789']]
Lista L3: [[], []]<jupyter_text>¿Qué nos entrega las siguientes instrucciones?<jupyter_code>v1 = L2[0]
v2 = L2[-1]
v3 = L3[1]
v4 = L1[3:]
v5 = L1[:3]
v6 = L2[2:3]
print(v1)
print(v2)
print(v3)
print(v4)
print(v5)
print(v6)<jupyter_output>True
[False, '789']
[]
[[4, 5, 6, 7, 8], 9]
[1, 2, 3]
[[1988, 4, 12]]<jupyter_text>Manejo de índices El manejo de índices en listas de listas aumenta un poco su complejidad, pero es importante entenderlo ya que es posible obtener cualquier valor y esto facilita mucho el trabajo. Hasta ahora sabemos que para obtener el valor de un elemento de una lista es necesario usar los paréntesis cuadrados o corchetes, `[ ]`. Este operador (operador rebanador) nos permite acceder a elementos de un iterable, es decir: lista y string. **Entonces, podemos usar tantas veces como queramos el operador rebanador, siempre y cuando tengamos al lado izquierda una lista o un string.** Volvamos al ejemplo anterior, es decir, con las listas `L1`, `L2`, y `L3`<jupyter_code>print('Lista L1:', L1)
print('Lista L2:', L2)
print('Lista L3:', L3)<jupyter_output>Lista L1: [1, 2, 3, [4, 5, 6, 7, 8], 9]
Lista L2: [True, 234, [1988, 4, 12], 'lista de listas', [False, '789']]
Lista L3: [[], []]<jupyter_text>Si sabemos que: `L1[3]` es la lista `[4, 5, 6, 7, 8]`, entonces podemos obtener el primer elemento de la siguiente manera:<jupyter_code>sub_lista = L1[3]
primer_elem = sub_lista[0]
print('El primer elemento de la sublista es:',primer_elem)<jupyter_output>El primer elemento de la sublista es: 4<jupyter_text>De una manera abreviada, y más conveniente, podemos escribir lo mismo de la siguiente manera:<jupyter_code>primer_elem = L1[3][0]
print('El primer elemento de la sublista es:',primer_elem)<jupyter_output>El primer elemento de la sublista es: 4<jupyter_text>Los paréntesis corchetes: `[ ]`, permiten acceder a la ubicación que le damos con el valor entero (positivo o negativo), pero además, **es posible realizar esto tantas veces como queramos siempre y cuando lo que este a lado izquierda sea una lista o un string.** Otro ejemplo: vamos a acceder a la palabra "de" del string "listas de listas" de la lista `L2`.<jupyter_code>print('Lista L2:', L2)
string_completo = L2[3]
palabra_de = string_completo[6:8]
print(palabra_de)<jupyter_output>de<jupyter_text>De manera abreviada, y **más conveniente** seria:<jupyter_code>print(L2[3][6:8])<jupyter_output>de<jupyter_text>Entonces, ¿qué nos entrega las siguientes instrucciones?<jupyter_code>print('Lista L1:', L1)
print('Lista L2:', L2)
print('Lista L3:', L3)
x1 = L1[3][-1]
x2 = L2[-1][0]
x3 = L2[3][9:]
print(x1)
print(x2)
print(x3)<jupyter_output>8
False
listas<jupyter_text>¿Y si generalizamos incluyendo más paréntesis corchetes?<jupyter_code>z1 = L1[3:][0][1]
z2 = L2[:][-1][-1][-1]
z3 = L2[::-1][1][::-1]
print(z1)
print(z2)
print(z3)<jupyter_output>5
9
satsil ed atsil<jupyter_text>Recorrerlas mediante `for` La forma de recorrer las listas mediante `for` es muy sencilla. Se debe seguir las mismas reglas que para recorrer una lista uni-dimensional.Se debe poner atención que valores toma ahora la variable que se crea en el `for`. Veamos un ejemplo:<jupyter_code>print('Lista L2:', L2)
for elemento in L2:
    print('Valor de la variable elemento:', elemento)<jupyter_output>Valor de la variable elemento: True
Valor de la variable elemento: 234
Valor de la variable elemento: [1988, 4, 12]
Valor de la variable elemento: lista de listas
Valor de la variable elemento: [False, '789']<jupyter_text>Veamos otro ejemplo:<jupyter_code>ramos = [['Progra','IWI-131', 3],
         ['Mate', 'MAT-021', 5],
         ['Fisica', 'FIS-100', 3],
         ['Ed.Fisica', 'DEW-100', 1],
         ['Inmanente', 'HRW-102', 2],
        ]

for nombre, sigla, c in ramos: # 3 variables en vez de 1
    print(nombre, 'tiene', c, 'creditos')<jupyter_output>Progra tiene 3 creditos
Mate tiene 5 creditos
Fisica tiene 3 creditos
Ed.Fisica tiene 1 creditos
Inmanente tiene 2 creditos<jupyter_text>**En la línea del `for` ahora hay 3 variables en vez de 1**. Esto es posible ya que sabemos que cada elemento de la lista ramos, **siempre**, tendrá 3 elementos.  La lista **ramos** es una lista de listas, donde cada sub-lista siempre tiene 3 elementos. Cada variable creada en la linea del `for`, tomará cada valor de las sub-listas. Esto será en orden, es decir: primera variable con el primer elemento de la sub-lista, y así sucesivamente. Siguiendo el ejemplo anterior, es posible recorrer cada sub-lista para así obtener cada elemento uno por uno sin que falte ninguno. Esto se hace con un `for` adicional:<jupyter_code>ramos = [['Progra','IWI-131', 3],
         ['Mate', 'MAT-021', 5],
         ['Fisica', 'FIS-100', 3],
         ['Ed.Fisica', 'DEW-100', 1],
         ['Inmanente', 'HRW-102', 2],
        ]

for asignatura in ramos: 
    print('Valor de la variable asignatura:', asignatura)
    for dato in asignatura:
        print('Valor de la variable dato:', dato)<jupyter_output>Valor de la variable asignatura: ['Progra', 'IWI-131', 3]
Valor de la variable dato: Progra
Valor de la variable dato: IWI-131
Valor de la variable dato: 3
Valor de la variable asignatura: ['Mate', 'MAT-021', 5]
Valor de la variable dato: Mate
Valor de la variable dato: MAT-021
Valor de la variable dato: 5
Valor de la variable asignatura: ['Fisica', 'FIS-100', 3]
Valor de la variable dato: Fisica
Valor de la variable dato: FIS-100
Valor de la variable dato: 3
Valor de la variable asignatura: ['Ed.Fisica', 'DEW-100', 1]
Valor de la variable dato: Ed.Fisica
Valor de la variable dato: DEW-100
Valor de la variable dato: 1
Valor de la variable asignatura: ['Inmanente', 'HRW-102', 2]
Valor de la variable dato: Inmanente
Valor de la variable dato: HRW-102
Valor de la variable dato: 2
{'fraction_non_alphanumeric': 0.13339981164478423, 'fraction_numerical': 0.04010858124203645, 'mean_word_length': 5.449446230796713, 'pattern_counts': {'":': 0, '<': 148, '<?xml version=': 0, '>': 145, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '46', 'dir': 'jupyter-structured-clean-dedup', 'id': '279407', 'license': 'BSD-3-Clause', 'n_tokens_mistral': 7504, 'n_tokens_neox': 7223, 'n_words': 2304, 'path': 'notebooks/07_Listas.ipynb', 'repo_name': 'dsanmartin/IWI-131', 'size': '18051'}