двумерная рекурсия python

#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 за ответ и подробное объяснение.