Как получить все возможные комбинации элементов из 2-мерного списка в Python? - PullRequest
5 голосов
/ 24 ноября 2011

Я не нашел лучшего способа сформулировать этот вопрос в заголовке.Если вы можете, пожалуйста, отредактируйте.

У меня есть список списков, подобный этому:

a = [['a','b'],[1,2]]

сейчас, я хотел бы функцию, которая выплевывает все возможные комбинации, как это:

[['a',1],['a',2],['b',1],['b',2]]

, где ни число списков в a не известно заранее, ни длина каждого из подсписков заранее неизвестна, но все выходящие комбинации должны содержать по 1 элементу из каждого подсписка.

Ответы [ 3 ]

12 голосов
/ 24 ноября 2011

Вам нужно itertools.product():

>>> list(itertools.product(*a))
[('a', 1), ('a', 2), ('b', 1), ('b', 2)]
0 голосов
/ 24 ноября 2011

Вот решение, использующее рекурсию, combs_r имеет accum дайджест head (следующий список в строке) для получения толще accum0, затем и вызывает себя ("рекурсия") с tail ( остальные списки) и теперь более толстый аккумулятор accum0.

Может быть интенсивным пользователем памяти, так как каждый вызов combs_r добавляет новое пространство имен до конца, когда все раскручивается. Человек, более осведомленный о внутренностях Python, может прокомментировать это.

Платит за изучение пролога, ИМХО.

def combs(ll):
    if len(ll) == 0:
        return []
    if len(ll) == 1:
         return [[item] for item in ll[0]]
    elif len(ll) == 2:
        return lmul(ll[0], [[item] for item in ll[1]])
    else:
        return combs_r(ll[1:], ll[0])

def combs_r(ll, accum):
    head = ll[0]
    tail = ll[1:]
    accum0 = []
    accum0 = lmul(head, accum)
    if len(tail) == 0:
        return accum0
    else:
        return combs_r(tail, accum0)

def lmul(head, accum):
    accum0 = []
    for ah in head:
        for cc in accum:
            #cc will be reused for each ah, so make a clone to mutate
            cc0 = [x for x in cc]
            cc0.append(ah)
            accum0.append(cc0)
    return accum0

sampleip = [['a','b','c'],[1,2], ['A', 'B']]
sampleip2 = [['a','b','c'],[1,2]]
sampleip1 = [['a','b','c']]
sampleip0 = []
print combs(sampleip0)
print combs(sampleip1)
print combs(sampleip2)
print combs(sampleip)
0 голосов
/ 24 ноября 2011

Это может быть то, что itertools.product() (что упоминает Свен) делает:

def combs(list1, list2):
    results = []
    for x in list1:
        for y in list2:
            l.append([x,y])
    return results
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...