2010-06-10 16 views
5

Tengo un conjunto de datos de eventos (tweets para ser específicos) que estoy tratando de bin/discretizar. El siguiente código parece funcionar bien hasta ahora (suponiendo 100 contenedores):Intercalar en intervalos de tiempo: ¿hay alguna manera mejor que utilizar la lista de compilación?

HOUR = timedelta(hours=1) 
start = datetime.datetime(2009,01,01) 
z = [dt + x*HOUR for x in xrange(1, 100)] 

Pero entonces, me encontré con esta línea fatídica en documentación de Python 'Esto hace posible una expresión idiomática para la agrupación de una serie de datos en grupos de longitud N usando zip(*[iter(s)]*n) '. La expresión zip funciona realmente, pero no puedo entender cómo (¿qué es el operador *, por ejemplo?). ¿Cómo podría usar para hacer que mi código sea más bonito? Supongo que esto significa que debo hacer un generador/iterable por el tiempo que yields el tiempo en graduaciones de una HORA?

+1

Ver [la sección "Llamadas" en los documentos de python] (http://docs.python.org/reference/expressions.html#calls) para la estrella. – Marian

Respuesta

5

voy a tratar de explicar zip(*[iter(s)]*n) en términos de un ejemplo más simple:

imagina que tienes la lista s = [1, 2, 3, 4, 5, 6]

iter(s) le da un objeto listiterator que producirá el siguiente número de s cada vez que pida un elemento.

[iter(s)] * n le da la lista con iter(s) en ella n veces, por ejemplo, [iter(s)] * 2 = [<listiterator object>, <listiterator object>] - la clave aquí es que estas son 2 referencias al mismo objeto iterador, no 2 objetos iteradores distintos.

zip toma un número de secuencias y devuelve una lista de tuplas, donde cada tupla contiene el elemento i-ésimo de cada una de las secuencias. p.ej. zip([1,2], [3,4], [5,6]) = [(1, 3, 5), (2, 4, 6)] donde (1, 3, 5) son los primeros elementos de los parámetros pasados ​​a zip y (2, 4, 6) son los segundos elementos de los parámetros pasados ​​a zip.

El * delante de *[iter(s)]*n convierte la [iter(s)]*n de ser una lista en ser múltiples parámetros se pasan a zip. por lo que si n es 2 obtenemos zip(<listiterator object>, <listiterator object>)

zip solicitará el siguiente elemento de cada uno de sus parámetros, pero debido a que estos son dos referencias a la misma iterador Esto dará lugar a (1, 2), que hace lo mismo nuevamente resulta en (3, 4) y otra vez que resulta en (5, 6) y luego no hay más elementos por lo que se detiene. De ahí el resultado [(1, 2), (3, 4), (5, 6)]. Esta es la agrupación de una serie de datos en grupos de longitud n como se mencionó.

+0

+1 para la excelente explicación de python – Anoyz

5

La expresión a partir de los documentos tiene el siguiente aspecto:

zip(*[iter(s)]*n) 

Esto es equivalente a:

it = iter(s) 
zip(*[it, it, ..., it]) # n times 

El [...]*n repite la lista n veces, y esto se traduce en una lista que contiene n referencias al mismo iterador.

Esto es de nuevo igual a:

it = iter(s) 
zip(it, it, ..., it) # turning a list into positional parameters 

El * antes de la lista se convierte en los elementos de la lista en los parámetros posicionales de la llamada de función.

Ahora, cuando se invoca zip, comienza de izquierda a derecha para llamar a los iteradores y obtener elementos que deben agruparse. Como todos los parámetros se refieren al mismo iterador, esto produce los primeros elementos n de la secuencia inicial. Luego, ese proceso continúa para el segundo grupo en la lista resultante, y así sucesivamente.

El resultado es el mismo que si se hubiera construido la lista como esta (evaluados de izquierda a derecha):

it = iter(s) 
[(it.next(), it.next(), ..., it.next()), (it.next(), it.next(), ..., it.next()), ...] 
+1

Brillante - muchas gracias por la explicación detallada - ¡tiene sentido ahora! – malangi

Cuestiones relacionadas