2013-07-02 3 views
20

Вот вопрос:Генерация всех комбинаций списка в Python

Учитывая список элементов в Python, как бы я ехать, чтобы получить все возможные комбинации элементов?

Есть несколько подобных вопросов на данном сайте, которые предлагают использовать itertools.combine, но возвращает только часть того, что мне нужно:

stuff = [1, 2, 3] 
for L in range(0, len(stuff)+1): 
    for subset in itertools.combinations(stuff, L): 
     print(subset) 

() 
(1,) 
(2,) 
(3,) 
(1, 2) 
(1, 3) 
(2, 3) 
(1, 2, 3) 

Как вы видите, он возвращает только те элементы, в строгом порядке , не возвращаясь (2, 1), (3, 2), (3, 1), (2, 1, 3), (3, 1, 2), (2, 3, 1) и (3, 2 , 1). Есть ли какое-то обходное решение? Кажется, я ничего не могу придумать.

+0

порядок не имеет значения в комбинациях, (2, 1) совпадает с (1, 2) –

+0

Хороший вопрос. Хотя технически вы могли бы написать свою собственную функцию, чтобы получить эти комбинации. – Sam

ответ

30

Использование itertools.permutations:

>>> import itertools 
>>> stuff = [1, 2, 3] 
>>> for L in range(0, len(stuff)+1): 
     for subset in itertools.permutations(stuff, L): 
       print(subset) 
...   
() 
(1,) 
(2,) 
(3,) 
(1, 2) 
(1, 3) 
(2, 1) 
(2, 3) 
(3, 1) 
.... 

помощь на itertools.permutations:

permutations(iterable[, r]) --> permutations object 

Return successive r-length permutations of elements in the iterable. 

permutations(range(3), 2) --> (0,1), (0,2), (1,0), (1,2), (2,0), (2,1) 
>>> 
2

itertools.permutations будет то, что вы хотите. По математическому определению порядок не имеет значения для combinations, то есть (1,2) считается идентичным (2,1). Принимая во внимание, что с permutations каждое отдельное упорядочение считается уникальной перестановкой, поэтому (1,2) и (2,1) совершенно разные.

6

Вы ищете itertools.permutations вместо этого?

От help(itertools.permutations),

Help on class permutations in module itertools: 

class permutations(__builtin__.object) 
| permutations(iterable[, r]) --> permutations object 
| 
| Return successive r-length permutations of elements in the iterable. 
| 
| permutations(range(3), 2) --> (0,1), (0,2), (1,0), (1,2), (2,0), (2,1) 

Пример кода:

>>> from itertools import permutations 
>>> stuff = [1, 2, 3] 
>>> for i in range(0, len(stuff)+1): 
     for subset in permutations(stuff, i): 
       print(subset) 


() 
(1,) 
(2,) 
(3,) 
(1, 2) 
(1, 3) 
(2, 1) 
(2, 3) 
(3, 1) 
(3, 2) 
(1, 2, 3) 
(1, 3, 2) 
(2, 1, 3) 
(2, 3, 1) 
(3, 1, 2) 
(3, 2, 1) 

Материал из Википедии, разница между перестановок и комбинаций:

Перестановка:

Неформально , перестановка множества объектов - это расположение этих объектов в определенном порядке. Например, существует шесть перестановок множества {1,2,3}, а именно (1,2,3), (1,3,2), (2,1,3), (2,3,1) , (3,1,2) и (3,2,1).

Комбинация:

В математике сочетание представляет собой способ выбора нескольких вещей из более крупной группы, где (в отличие от перестановок) порядок не имеет значения.

9

Вы можете создавать все комбинации списка в Python, используя этот простой код

import itertools 

a = [1,2,3,4] 
for i in xrange(1,len(a)+1): 
    print list(itertools.combinations(a,i)) 

Результат:

[(1,), (2,), (3,), (4,)] 
[(1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4)] 
[(1, 2, 3), (1, 2, 4), (1, 3, 4), (2, 3, 4)] 
[(1, 2, 3, 4)] 
+0

Вопрос просил увидеть (2, 1) в результатах. Где (2, 1) в вашем ответе? –

+2

Комбинация (2, 1) и (1, 2) оба являются одним и тем же чуваком. –

+1

Несмотря на то, что в вопросе есть «комбинации», это означает перестановки. Прочтите его до конца и убедитесь, что оба (2, 1) и (1, 2) ожидаются от OP. –

0

Я предполагаю, что вы хотите, чтобы все возможные комбинации, как 'наборы' значений.Вот кусок кода, который я написал, что может помочь дать Вам идею:

def getAllCombinations(object_list): 
    uniq_objs = set(object_list) 
    combinations = [] 
    for obj in uniq_objs: 
     for i in range(0,len(combinations)): 
      combinations.append(combinations[i].union([obj])) 
     combinations.append(set([obj])) 
return combinations 

Вот пример:

combinations = getAllCombinations([20,10,30]) 
combinations.sort(key = lambda s: len(s)) 
print combinations 
... [set([10]), set([20]), set([30]), set([10, 20]), set([10, 30]), set([20, 30]), set([10, 20, 30])] 

Я думаю, что это имеет п! сложность времени, поэтому будьте осторожны. Это работает, но не может быть наиболее эффективным

2

Вот решение без itertools

Первых позволяет определить преобразование между индикатором вектором 0 и 1 с и подсписком (1, если элемент находится в подсписке)

def indicators2sublist(indicators,arr): 
    return [item for item,indicator in zip(arr,indicators) if int(indicator)==1] 

Далее Ну определим отображение числа между 0 и 2^n-1 в его двоичный вектор представления (с использованием функции format струны):

def bin(n,sz): 
    return ('{d:0'+str(sz)+'b}').format(d=n) 

Все, что нам осталось сделать, это перебирать все возможные номера, и вызвать indicators2sublist

def all_sublists(arr): 
    sz=len(arr) 
    for n in xrange(0,2**sz): 
    b=bin(n,sz) 
    yield indicators2sublist(b,arr) 
-1

просто подумал, что я бы поставил это там, так как я не мог нормально КАЖДЫЙ возможный результат и имея в виде, у меня есть только самая сырцовый самый основные знания, когда дело доходит до питона и есть, вероятно, гораздо более элегантное решение ... (и извините за плохие имена переменных

тестирование = [1, 2, 3]

testing2 = [0]

п = -1

Защиту testingSomethingElse (номер):

try: 

    testing2[0:len(testing2)] == testing[0] 

    n = -1 

    testing2[number] += 1 

except IndexError: 

    testing2.append(testing[0]) 

в то время как True:

n += 1 

testing2[0] = testing[n] 

print(testing2) 

if testing2[0] == testing[-1]: 

    try: 

     n = -1 

     testing2[1] += 1 

    except IndexError: 

     testing2.append(testing[0]) 

    for i in range(len(testing2)): 

     if testing2[i] == 4: 

      testingSomethingElse(i+1) 

      testing2[i] = testing[0] 

я отделался == 4, потому что я работаю с целыми числами, но вам может потребоваться изменить это соответственно ...

Смежные вопросы