Ver Mensaje Individual
  #1 (permalink)  
Antiguo 14/12/2011, 20:18
Avatar de razpeitia
razpeitia
Moderador
 
Fecha de Ingreso: marzo-2005
Ubicación: Monterrey, México
Mensajes: 7.321
Antigüedad: 19 años
Puntos: 1360
[Aporte] Comprensión de listas

Vamos empezar comprensión de listas sin comprensión de listas.

¿Cuantas veces te has topado con este patrón?

Código Python:
Ver original
  1. def some_function(x):
  2.     return x * 10
  3.  
  4. some_list = [1, 2, 3]
  5. some_new_list = []
  6. for i in some_list:
  7.     x = some_function(i)
  8.     some_new_list.append(x)

Básicamente lo que hacemos es, tenemos una lista y queremos que cada elemento pase por una función, en este caso nuestra función some_function solo multiplica por 10 un elemento dado x.

Como sabemos en python todo es un objeto y las funciones no son una excepción.

Así que podemos pasar una función como parámetro.

Código Python:
Ver original
  1. def map_list(function, some_list):
  2.     some_new_list = []
  3.     for i in some_list:
  4.         some_new_list.append(function(i))
  5.     return some_new_list
Genial ahora hicimos una función que le pasamos una función y una lista como parámetro y nos regresa una lista nueva con cada elemento "procesado".

Curiosamente esta función ya existe en python y se llama map.

Vamos a ver como trabaja.

Código Python:
Ver original
  1. def f(x):
  2.     return x * 10
  3.  
  4. l = [1, 2, 3]
  5. map(f, l)
  6. #map regresa [10, 20, 30]

Esto es genial excepto por un pequeño detalle.

Si quiero procesar cada elemento en una lista con muchas funciones esto se vuelve feo. Sin mencionar el uso de memoria.
Código Python:
Ver original
  1. map(f3, map(f2, map(f1, l)))

Una solución sería hacer una nueva función
Código Python:
Ver original
  1. def f4(x):
  2.     return f3(f2(f1(x)))
  3.  
  4. map(f4, l)

Desafortunadamente en las versiones de python 3.x map, filter y reduce no están incluidas.

Entonces el código que escriba usando map, filter o reduce no puede ser ejecutado en python 3.x

Sin embargo puedes usar compresión de listas.
Entonces en vez de tener
Código Python:
Ver original
  1. def f(x):
  2.     return x * 10
  3. l = [1, 2, 3]
  4. [f(i) for i in l] #-> [10, 20, 30]

El truco de esto es leerlo tal como lo harías en español o ingles f(i) para i en l, entonces esto te genera una lista "procesada" (esto es que cada elemento fue procesado por una función. Ademas puedes ahorrarte la función y escribirlo directamente en la comprensión de listas.

Código Python:
Ver original
  1. l = [1, 2, 3]
  2. [i * 10 for i in l] #-> [10, 20, 30]
Mucho mas compacto.

Ahora que pasa si deseo seleccionar ciertos elementos que cumplan con algún criterio. Y vamos a empezar con el código sencillo.

Código Python:
Ver original
  1. some_list = [10, -1, 2, 4, 5]
  2. some_new_list = []
  3. for i in some_list:
  4.     if i > 5:
  5.         some_new_list.append(i)

Lo único que hacemos es seleccionar o filtrar aquellos elementos que cumplan con un criterio, en este caso que sean mayor a 5.

Podemos hacer esto con filter, que recibe una función y una lista y regresa una lista filtrada por la función.

Código Python:
Ver original
  1. def f(x):
  2.     return x > 5
  3. l = [10, -1, 2, 4, 5]
  4. filter(f, l) #[10]

Y lo mejor de todo es que también lo podemos hacer con compresión de listas.

Código Python:
Ver original
  1. l = [10, -1, 2, 4, 5]
  2. [i for i in l if i > 5]# -> [10]
Mucho mas simple.

Ahora vamos a generar una matriz con compresión de listas.

En otros lenguajes una matriz es una tabla de elementos, las tablas tienen filas y columnas, así que accedemos a los elementos por medio de una fila y una columna, en ese orden.

En python esto sería una matriz* de 2x3.
Código Python:
Ver original
  1. # columna
  2. # |
  3. # v
  4. [[1, 2, 3], #<- fila
  5.  [4, 5, 6]]
Tiene 2 filas y 3 columnas.
*Formalmente no es una matriz

Entonces vamos a generar una matriz inicialmente con ceros de tamaño m x n donde m es el numero de filas y n el numero de columnas.
Código Python:
Ver original
  1. def create_matrix(m, n):
  2.     return [[0 for j in range(n)] for i in range(m)]
Lo hicimos en una sola linea!!!

¿Como es esto posible?

Una de las ventajas de la compresión de listas es que las puedes anidar y puedes generar listas de listas.

Pero vamos a ver el código paso a paso
[0 for j in range(n)]
Esto genera una lista con n ceros. Y simplemente lo que hace es generar una fila.

[... for i in range(m)]
Esto genera ... m veces.

Si los juntamos
[[0 for j in range(n)] for i in range(m)]
Entonces generamos m filas, y cada fila tiene n columnas.

Hasta aquí espero haberte ayudado a comprender un poco mejor compresión de listas.

Última edición por razpeitia; 19/10/2014 a las 11:24