El iterador groupby
devuelve tuplas del resultado de la función de agrupamiento y un nuevo iterador que está vinculado al mismo iterador "externo" en el que está trabajando el operador groupby
. Cuando aplique dict()
al iterador devuelto por groupby
sin consumir este iterador "interno", groupby
tendrá que avanzar el iterador "externo" por usted. Debe darse cuenta de que la función groupby
no actúa en una secuencia, sino que convierte dicha secuencia en un iterador por usted.
Quizás esto se explica mejor con algunas metáforas y movimientos manuales. Por favor sigue mientras formamos una línea de cubo.
Imagina iteradores como una persona que extrae agua en baldes de un pozo. Él tiene un número ilimitado de cubos para usar, pero el pozo puede ser finito. Cada vez que le pidas a esta persona un cubo de agua, él saca un cubo nuevo del pozo de agua y se lo pasa.
En el caso groupby
, inserta a otra persona en su cadena de cubos en ciernes. Esta persona no pasa balones de inmediato. Le pasa el resultado de las instrucciones que le dio más otra persona cada vez que solicita un depósito, quien luego le pasará los depósitos a través de la persona groupby
a quien pregunte, siempre que coincidan con el mismo resultado de las instrucciones. El pasador de cubos groupby
dejará de pasar estos cubos si el resultado de las instrucciones cambia.Por lo tanto, well
proporciona intervalos a groupby
, que pasa esto a una persona por grupo, group A
, group B
, y así sucesivamente.
En su ejemplo, el agua está numerada, pero solo puede haber 1000 cubos extraídos del pozo. Esto es lo que sucede cuando se pasan luego a la persona a la llamada groupby
dict()
:
Su llamada dict()
pide groupby
de un cubo. Ahora, groupby
pide un balde de la persona en el pozo, recuerda el resultado de las instrucciones dadas, aferrándose al balde. Al dict()
pasará el resultado de las instrucciones (False
) más una nueva persona, group A
. El resultado se almacena como la clave, y la persona group A
, que quiere extraer cubos, se almacena como valor. Esta persona es , no, pero aún pide cubos, porque nadie lo está pidiendo.
Su llamada dict()
pregunta groupby
por otro cubo. groupby
tiene estas instrucciones, y busca el próximo cubo donde cambia el resultado. Todavía estaba aferrado al primer cubo, nadie lo pidió, por lo que arroja este cubo. En cambio, solicita el siguiente cubo del pozo y usa sus instrucciones. El resultado es el mismo que antes, ¡así que arroja este nuevo cubo también! Más agua pasa por el piso, y así pasan los siguientes 499 cubos. Solo cuando se pasa el depósito con el número 501 cambia el resultado, por lo que ahora groupby
encuentra a otra persona para dar instrucciones (persona group B
), junto con el nuevo resultado, True
, pasando estos dos a dict()
.
Su llamada dict()
almacena True
como clave, y la persona group B
como el valor. group B
no hace nada, nadie le pide agua.
Su dict()
pide otro cucharón. groupby
derrama más agua, hasta que contiene un cubo con el número 999, y la persona en el pozo se encoge de hombros y dice que ahora el pozo está vacío. groupby
dice dict()
el pozo está vacío, no hay más cubos, ¿podría dejar de preguntar? Todavía contiene el cubo con el número 999, porque nunca tiene que dejar espacio para el siguiente cubo del pozo.
Ahora viene, pidiendo dict()
para la cosa asociada con la clave True
, que es la persona group B
. Pase group B
a list()
, que por lo tanto pedirá group B
para todos los cubos group B
pueden obtener. group B
se remonta a groupby
, que tiene un solo cubo, el cubo con el número 999, y el resultado de las instrucciones para este cubo coinciden con lo que group B
está buscando. Así que este cubo group B
da a list()
, luego se encoge de hombros porque no hay más cubos, porque groupby
se lo dijo.
Luego, pregunte dict()
por la persona asociada con la clave False
, que es la persona group A
. Por ahora, groupby
no tiene nada que ofrecer, el pozo está seco y está parado en un charco de 999 cubos de agua con números flotando. Su segundo list()
no obtiene nada.
¿La moraleja de esta historia? ¡Solicite inmediatamente todos los baldes de agua cuando hable con groupby
, porque los derramará todos si no lo hace! Los iteradores son como las escobas en la fantasía, moviendo diligentemente el agua sin comprender, y es mejor que se quede sin agua si no sabe cómo controlarla.
Aquí es código que haría lo que espera (con un poco menos de agua para evitar inundaciones):
>>> from itertools import groupby
>>> keyfunc = lambda x : x > 5
>>> obj = dict((k, list(v)) for k, v in groupby(range(10), keyfunc))
>>> obj(True)
[0, 1, 2, 3, 4, 5]
>>> obj(False)
[6, 7, 8, 9]
Quizás quiso decir "El aprendiz de brujo"? ¿O tal vez Fantasia tiene escobas para llevar agua también? –
@ReblochonMasque The Sorcerer's Apprentice [es una parte de Fantasia] (https://en.wikipedia.org/wiki/Fantasia_%281940_film%29#Program). –
Ok, gracias @MartijnPieters, no lo sabía. –