#python #python-3.x #recursion #combinations
#python #python-3.x #рекурсия #комбинации
Вопрос:
У меня есть список пар ключей и их возможных значений, которые анализируются из командной строки. например:
[('-a',['1','2','3']), ('-b',['1','2'])]
моя цель — создавать комбинации следующим образом:
prefix -a=1 -b=1 suffix
prefix -a=1 -b=2 suffix
prefix -a=2 -b=1 suffix
prefix -a=2 -b=2 suffix
prefix -a=3 -b=1 suffix
prefix -a=3 -b=2 suffix
проблема в том, что список может быть любой длины, как и значения во вложенных списках.
Возможным решением было бы использовать какую-то рекурсию, пока то, что я написал, не дает мне того, что я хочу:
def runner(args, comd=""):
for i in range(len(args)):
op, vals = args[i]
for val in vals:
comd = op "=" val " " runner(args[1:], comd)
if i == len(args) - 1:
print ("prefix " comd " suffix")
return comd
Ответ №1:
Вы хотите выполнить декартово произведение двух списков. Используйте itertools.product()
для этого. Например:
>>> my_list = [('-a',['1','2','3']), ('-b',['1','2'])]
>>> from itertools import product
>>> list(product(my_list[0][1], my_list[1][1]))
[('1', '1'), ('1', '2'), ('2', '1'), ('2', '2'), ('3', '1'), ('3', '2')]
Он выдает list
все комбинации tuple
из обоих списков.
Теперь, переходя к вашей проблеме, ниже приведен пример кода:
my_list = [('-a',['1','2','3']), ('-b',['1','2'])]
keys, value_list = zip(*my_list)
for item in product(*value_list):
val_list = ['{}={}'.format(key, val) for key, val in zip(keys, item)]
print 'prefix {} suffix'.format(' '.join(val_list))
# Output:
prefix -a=1 -b=1 suffix
prefix -a=1 -b=2 suffix
prefix -a=2 -b=1 suffix
prefix -a=2 -b=2 suffix
prefix -a=3 -b=1 suffix
prefix -a=3 -b=2 suffix
Объяснение:
zip([iterable, ...])
возвращает список кортежей, где i-й кортеж содержит i-й элемент из каждой последовательности аргументов или итераций. Возвращаемый список усекается по длине до длины кратчайшей последовательности аргументов. Например, в приведенном выше коде:
>>> keys, value_list = zip(*my_list) # zipping the unwrapped "my_list"
>>> keys # value of keys
('-a', '-b')
>>> value_list # value of values_list
(['1', '2', '3'], ['1', '2'])
Затем я выполняю декартово произведение values_list
(как объяснялось в самом начале) и снова выполняю zip
для keys
и каждого item
декартова произведения.
Комментарии:
1. Где находятся a и b? Кроме того, вы действительно собираетесь вручную индексировать dict с 1000000 парами ключ / значение?
2. Ваш код не выполняет то, что делает код OP, поэтому независимо от общего решения вы можете дать правильное решение или удалить ответ.
3. Спасибо @anonymous за ответ и подробное объяснение.