| You are here: Inicio > Inmersión en Python > Programación Funcional > Revisión del filtrado de listas | << >> | ||||
Inmersión en PythonPython de novato a experto |
|||||
Ya está familiarizado con el uso de listas por comprensión para filtrar listas. Hay otra manera de conseguir lo mismo que algunas personas consideran más expresiva.
Python incorpora una función filter que toma dos argumentos, una función y una lista, y devuelve una lista.[18] La función que se pasa como primer argumento a filter debe a su vez tomar un argumento, y la lista que devuelva filter contendrá todos los elementos de la lista que se le pasó a filter para los cuales la función del primer argumento devuelve verdadero.
¿Lo entendió? No es tan difícil como suena.
>>> def odd(n):... return n % 2 ... >>> li = [1, 2, 3, 5, 9, 10, 256, -3] >>> filter(odd, li)
[1, 3, 5, 9, -3] >>> [e for e in li if odd(e)]
>>> filteredList = [] >>> for n in li:
... if odd(n): ... filteredList.append(n) ... >>> filteredList [1, 3, 5, 9, -3]
| odd usa la función incorporada de módulo “%” para devolver True si n es impar y False si n es par. | |
| filter toma dos argumentos, una función (odd) y una lista (li). Itera sobre la lista e invoca odd con cada elemento. Si odd devuelve verdadero (recuerde, cualquier valor diferente a cero es verdadero en Python), entonces se incluye el elemento en la lista devuelta, en caso contrario se filtra. El resultado es una lista con sólo los números impares que había en la original, en el mismo orden en que aparecían allí. | |
| Puede conseguir lo mismo usando listas por comprensión, como vio en Sección 4.5, “Filtrado de listas”. | |
| Podría hacer lo mismo también con un bucle for. Dependiendo de su bajage como programador, esto puede parecer más “directo”, pero las funciones como filter son mucho más expresivas. No sólo son más fáciles de escribir, sino también de leer. Leer el bucle for es como estar demasiado cerca de una pintura; ve todos los detalles pero puede llevarle unos segundos dar unos pasos atrás y ver todo el cuadro: “¡Oh, está filtrando la lista!” |
files = os.listdir(path)
test = re.compile("test\.py$", re.IGNORECASE)
files = filter(test.search, files) 
| Como vio en Sección 16.2, “Encontrar la ruta”, path puede contener la ruta completa o parcial del directorio del script que se está ejecutando o una cadena vacía si se ejecutó desde el directorio actual. De cualquier manera, files acabará teniendo los nombres de los ficheros que están en el mismo directorio que el script. | |
| Esto es una expresión regular compilada. Como vio en Sección 15.3, “Refactorización”, si va a utilizar la misma expresión regular una y otra vez debería compilarla para que rinda mejor. El fichero compilado tiene un método search que toma un solo argumento, la cadena a buscar. Si la expresión regular coincide con la cadena, el método search devuelve un objeto Match que contiene información sobre la coincidencia; en caso contrario devuelve None, el valor nulo de Python. | |
| Vamos a invocar el método search del objeto que contiene la expresión regular compilada (test) con cada elemento de la lista files. Si coincide la expresión regular, el método devolverá un objeto Match que Python considera verdadero, así que el elemento se incluirá en la lista devuelta por filter. Si la expresión regular no coincide el método search devolverá None que Python considera falso, así que no se incluirá el elemento. |
Nota histórica. Las versiones de Python anteriores a la 2.0 no tienen listas por comprensión, así que no podría filtrar usándolas; la función filter, era lo único a lo que se podía jugar. Incluso cuando se introdujeron las listas por comprensión en 2.0 algunas personas siguieron prefiriendo la vieja filter (y su compañera map, que veremos en este capítulo). Ambas técnicas funcionan y la que deba usar es cuestión de estilo. Se está comentando que map y filter podrían quedar obsoletas en una versión futura de Python, pero no se ha tomado aún una decisión.
files = os.listdir(path)
test = re.compile("test\.py$", re.IGNORECASE)
files = [f for f in files if test.search(f)] 
[18] Técnicamente, el segundo argumento de filter puede ser cualquier secuencia, incluyendo listas, tuplas y clases que actúen como listas definiendo el método especial __getitem__. Si es posible, filter devolverá el mismo tipo que le pasó, así que filtrar una lista devuelve una lista pero filtrar una tupla devuelve una tupla.
<< Encontrar la ruta |
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | |
Revisión de la relación de listas >> |