Digamos que eu tenho uma lista Python representando intervalos para algumas variáveis:
conditions = [['i', (1, 5)], ['j', (1, 2)]]
Isso representa que a variável i
varia de 1 a 5 e, dentro desse loop, a variável j
varia de 1 a 2. Quero um dicionário para cada combinação possível:
{'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}
A razão é que eu quero iterar sobre eles. Mas como todo o espaço é muito grande, não quero gerar todos eles, armazená-los e iterar sobre essa lista de dicionários. Pensei em usar o seguinte procedimento recursivo, mas preciso de ajuda com a yield
parte. Onde deveria estar? Como evito geradores aninhados?
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)
Agora eu gostaria de poder fazer:
for valued_indices in iteration(conditions, 0, {}):
...
yield
poryield from
na última linha da sua função.Respostas:
É um caso em que pode ser mais fácil dar um passo atrás e começar de novo.
Vamos começar separando as teclas e os intervalos, usando um truque conhecido que envolve
zip
:(A correspondência entre os dois preserva o emparelhamento original;
intervals[i]
é o intervalo da variávelkeys[i]
para todosi
.)Agora, vamos criar objetos de intervalo adequados a partir desses intervalos
Podemos calcular o produto desses
range
objetosque você deve reconhecer como os valores a serem usados para cada ditado. Você pode compactar cada um desses valores com as chaves para criar um conjunto apropriado de argumentos para o
dict
comando. Por exemplo:Juntando tudo isso, podemos iterar o produto para produzir cada um
dict
, produzindo-o.fonte
Talvez você possa simplificar um pouco com uma compreensão interna do gerador e
yield from
:use como:
fonte
dict_factory(*args)
então ... Hmmm ...Não tenho certeza se você precisa usar recursão especificamente ou não, mas pode gerá-los usando o método do produto itertools para gerar todas as combinações. isso está escrito de tal maneira que você pode ter condições de 1 a n e ainda deve funcionar e devolvê-lo item por item.
RESULTADO
fonte