Digamos que tengo una lista de Python que representa rangos para algunas variables:
conditions = [['i', (1, 5)], ['j', (1, 2)]]
Esto representa que la variable ivaría de 1 a 5, y dentro de esa variable de bucle jvaría de 1 a 2. Quiero un diccionario para cada combinación posible:
{'i': 1, 'j': 1}
{'i': 1, 'j': 2}
{'i': 2, 'j': 1}
{'i': 2, 'j': 2}
{'i': 3, 'j': 1}
{'i': 3, 'j': 2}
{'i': 4, 'j': 1}
{'i': 4, 'j': 2}
{'i': 5, 'j': 1}
{'i': 5, 'j': 2}
La razón es que quiero iterar sobre ellos. Pero debido a que todo el espacio es demasiado grande, no quiero generarlos todos, almacenarlos y luego iterar sobre esa lista de diccionarios. Pensé en usar el siguiente procedimiento recursivo, pero necesito ayuda con la yieldparte. Donde debe ser ¿Cómo evito los generadores anidados?
def iteration(conditions, currentCondition, valuedIndices):
if currentCondition == len(conditions):
yield valuedIndices
else:
cond = conditions[currentCondition]
index = cond[0]
lim1 = cond[1][0]
lim2 = cond[1][1]
for ix in range(lim1, lim2 + 1):
valuedIndices[index] = ix
yield iteration(conditions, currentCondition + 1, valuedIndices)
Ahora me gustaría poder hacer:
for valued_indices in iteration(conditions, 0, {}):
...

yieldconyield fromen la última línea de su función.Respuestas:
Este es un caso en el que podría ser más fácil dar un paso atrás y comenzar de nuevo.
Comencemos separando las claves y los intervalos, usando un truco bien conocido que involucra
zip:(La correspondencia entre los dos conserva el emparejamiento original;
intervals[i]es el intervalo para la variablekeys[i]para todosi).Ahora, creemos objetos de rango adecuados a partir de esos intervalos
Podemos calcular el producto de estos
rangeobjetos.que debe reconocer como los valores a utilizar para cada dict. Puede comprimir cada uno de esos valores con las claves para crear un conjunto apropiado de argumentos para el
dictcomando. Por ejemplo:Al unir todo esto, podemos iterar sobre el producto para producir cada uno
dicta su vez, produciéndolo.fuente
Quizás pueda simplificar un poco con una comprensión interna del generador y
yield from:usar como:
fuente
dict_factory(*args)entonces ... Hmmm ...No estoy seguro de si necesita usar la recursión específicamente o no, pero podría generarlos utilizando el método del producto itertools para generar todas las combinaciones. esto está escrito de tal manera que puede tener condiciones de 1 a n y aún debería funcionar y devolverle artículo por artículo.
SALIDA
fuente