Skip to content

Latest commit

 

History

History
413 lines (308 loc) · 9.47 KB

listas2.org

File metadata and controls

413 lines (308 loc) · 9.47 KB

Listas

Ciclos for con índices

Anteriormente vimos que podríamos iterar directamente sobre una lista con la siguiente sintaxis:

for element in somelist:
    ...

La cual podemos iterar usando una lista de índices y un índice dentro del ciclo:

for i in range(len(somelist)):
   element = somelist[i]

Ciclos for con índices

Ejemplo: usando índices, generar dos listas con los grados Celsius y los grados Fahrenheit y después con un sólo ciclo imprimir la tabla de conversión desde -10 hasta 40 grados Celsius con intervalos de 2.5

Cdegrees = []
n = 21
C_min = -10
C_max = 40
dC = (C_max - C_min) / float(n - 1)
for i in range(n):
    C = -10 + i * dC
    Cdegrees.append(C)

Fdegrees = []
for C in Cdegrees:
    F = (9.0/5) * C + 32
    Fdegrees.append(F)

for i in range(len(Cdegrees)):
    C = Cdegrees[i]
    F = Fdegrees[i]
    print("%5.1f %5.1f"% (C, F))

Ciclos for con índices

Otra forma de construir listas es usando la notación:

lista = [0] * n

La cuál creará una lista de tamaño n llena de ceros. Usando esta construcción, podemos reescribir el código anterior de la siguiente forma:

n = 21; C_min = -10; C_max = 40; dC = (C_max - C_min) / float(n - 1)

Cdegrees = [0] * n
for i in range(len(Cdegrees)):
    Cdegrees[i] = -10 + i*dC

Fdegrees = [0] * n
for i in range(len(Cdegrees)):
    Fdegrees[i] = (9.0/5)*Cdegrees[i] + 32

for i in range(len(Cdegrees)):
    print("%5.1f %5.1f" % (Cdegrees[i], Fdegrees[i])

Cambiando elementos de una lista

Tenemos dos formas alternativas de recorrer una lista, ya sea sobre elementos o sobre índices. Supongamos que queremos cambiar la lista Cdegrees por agregar 5 a cada elemento. Podemos intentar:

for c in Cdegrees:
    c += 5

Pero también podemos:

for i in range(len(Cdegrees)):
    Cdegrees[i] += 5

¿Qué es lo que sucede con ambas ejecuciones?

Cambiando elementos de una lista

Vimos que el último ciclo se encarga de actualizar los valores de la lista. Además de esa forma, existe una forma de recorrer una lista de tal forma que obtengamos el índice y el elemento de la lista. Esta construcción la tenemos de la siguiente forma:

for i, c in enumerate(Cdegrees):
    Cdegrees[i] = c + 5

Comprensión de listas

Debido a que el recorrido dentro de una lista y crear elementos dentro de la misma, es una tarea frecuente, Python tiene una sintaxis compacta para hacer esto, llamado Comprensión de listas (list comprehension). La sintaxis general es:

newlist = [E(e) for e in list]

Donde E(e) representa una expresión envolviendo al elemento e. Aquí hay tres ejemplos:

Cdegrees = [-5 + i * 0.5 for i in range(n)]
Fdegrees = [(9.0/5) * C + 32 for C in Cdegrees]
C_plus_4 = [C + 5 for C in Cdegrees]

Atravesando multiples listas simultáneamente

Anteriormente generamos una tabla de conversión usando Cdegrees y Fdegrees. Para hacerlo necesitamos recorrer ambas listas. Usar la sintaxis for element in list no es útil para nuestro proposito y no queremos usar indices. Python va proveer una alternativa a este problema usando la siguiente sintaxis:

for e1, e2, e3, ... in zip(list1, list2, list3):
   <usar e1, e2, e3, etc...>

La función zip transforma las n listas (list1, list2, *list3, …) en una lista de n-tuplas, donde cada n-tupla (e1, e2, e3, ..) tiene su primer elemento (e1) desde la primera lista (list1), el segundo elemnto (e2) desde la segunda lista (list2) y así sucesivamente.

for C, F in zip(Cdegrees, Fdegrees):
    print("%5.1f %5.1f"%(C,F))

Listas anidadas

Las listas anidadas son listas cuyos elementos en la lista son listas en si mismas.

Por ejemplo, podemos tener una lista con las listas Cdegrees y Fdegrees que represente nuestra tabla.

Cdegrees = list(range(-20, 41, 5))
Fdegrees = [(9.0/5)*C + 32 for C in Cdegrees]

table = [Cdegrees, Fdegrees]
xo
>> [[-20, -15, -10, -5, 0, 5, 10, 15, 20, 25, 30, 35, 40]
  , [-4.0, 5.0, 14.0, 23.0, 32.0, 41.0, 50.0, 59.0, 68.0, 77.0, 86.0, 95.0, 104.0]]

Listas anidadas

A pesar de lo anterior, quisieramos tener una lista que tuvieras listas de dos elementos que representen parejas [C, F] y para tener esto necesitamos la siguiente construcción:

table = []
for C, F in zip(Cdegrees, Fdegrees):
    table.append([C, F])

o de forma más compacta:

table = [[C, F] for C, F in zip(Cdegrees, Fdegrees)]

Imprimiendo objetos

Python provee un módulo para imprimir objetos de forma bonita. Este módulo es pprint:

import pprint
pprint.print(table)

Además de que scitools va proveer un módulo para proveer total control sobre la impresión de números flotantes dentro de listas.

import pprint, scitools.pprint2
somelist = [15.8, [0.2, 1.7]]
pprint.pprint(somelist)
#[15.800000000000001, [0.20000000000000001, 1.7]]
scitools.pprint2.pprint(somelist)
# [15.8, [0.2, 1.7]]
>>> # default output is ’%g’, change this to
scitools.pprint2.float_format =%.2escitools.pprint2.pprint(somelist)
# [1.58e+01, [2.00e-01, 1.70e+00]

Extrayendo sublistas

Python tiene una bonita sintaxis para extraer partes de una listas. Estas partes son conocidas como sublistas o slices.

A{i:]
Es la sublista iniciando en el índice i y continuando hasta el final de A.
A = [2, 3.5, 8, 10]
A[2:]
A[i:j]
Es la sublista iniciando en en el índice i y terminando en el índice j - 1.
A[1:3]
A[:j]
Es la sublista que inicia en el índice 0 y termina en el índice j-1 de A.
A[:3]
A[1:-1]
Extrae todos los elementos excepto el último y el primero.
A[:]
Es toda la lista

Extrayendo sublistas

También podemos extraer sublistas de listas anidadas:

table[4:]
table[4:7][0:2]

Las sublistas son siempre copias de lista de original, así que si modificamos las sublistas, la lista original se mantiene sin cambios.

l1 = [1, 4, 3]; l2 = l1[:-1]
l2
l1[0] = 100
l1; l2

El hecho de que crear sublistas son copias, puede ser ilustrado con el siguiente código:

B = A[:]
C = A
B == A
B is A
C is A

Recorriendo listas anidadas

Vimos anteriormente que recorrer la lista anidada table puede ser hecho de la siguiente forma:

for C, F in table:
    <to do something>

Supongamos ahora que necesitamos una lista anidada de puntajes scores para llevar el control de puntos de varios jugadores. La lista scores[i] representa los puntajes del jugador i.

Cada una de las listas scores[i] tiene distinto tamaño, entonces, ¿Cómo recorremos las listas?

Recorriendo listas anidadas

scores = []
scores.append([12, 16, 11, 12])
scores.append([9])
scores.append([6, 9, 11, 14, 17, 15, 14, 20])

Hay dos formas de recorrer esta lista:

for p in range(len(scores)):
    for g in range(len(scores[p])):
        print("%4d"%score)
    print


for player in scores:
    for point in player:
        print("%4d"%score)
    print

Tuplas

Las tuplas son muy similares a las listas, pero las tuplas no permiten cambios. Esto es, las tuplas pueden ser vistas como listas constantes.

t = (2, 4, 6, 'temp.pdf')
t1 = 2, 4, 6, 'temp.pdf'
for element in 'myfile.txt', 'yourfile.txt', 'herfile.txt':
    print(element)

Muchas de las funciones usadas para las listas, también se encuentran disponibles para las tuplas. Por ejemplo:

t = t + (-1.0, -2.0)
t
t[1]
t[2:]
6 in t

Mientras que las operaciones de modificación no van a funcionar:

>>> t[1] = -1
...
TypeError: object does not support item assignment
>>> t.append(0)
...
AttributeError: ’tupleobject has no attributeappend>>> del t[1]
...
TypeError: object doesn't support item deletion

Tuplas

¿Cuándo necesitamos usar tuplas cuando podemos hacer más con listas?

  • Las tuplas protegen contra cambios accidentales en sus contenidos
  • Código basado en listas es mucho más rápido que en listas
  • Las tuplas son frecuentemente usadas en software hecho en Python que seguramente vas a hacer uso de el, así que necesitas conocer este tipo de datos.

Ejercicio

Dado un arreglo de números enteros aleatorios, encontrar el par de números cuya suma sea más cercana a cero. Por ejemplo, en el arreglo [45, -29, -96, -7, -17, 72, -60], los dos enteros cuya suma es más cercana a cero son -60 y 72.

La tarea es escribir un programa que encuentre la suma más cercana a cero.

Ejercicio

Solución

def cercano_a_cero(int_array):
    cercano_a_cero = [float("inf")]
    for index, operando1 in enumerate(int_array):
        for operando2 in list(int_array[index+1:]):
            suma_ints = [operando1, operando2]
            if abs(sum(suma_ints)) < abs(sum(cercano_a_cero)):
                cercano_a_cero = suma_ints
    return cercano_a_cero

if __name__ == "__main__":
    print(cercano_a_cero([45, -29, -96, -7, -17, 72, -60]))