2016-01-26 6 views
-4

есть много вопросов и ответов о объединении и объединении списков в python, но я не нашел способ создать полную комбинацию всех элементов.Объединить все элементы n списков в python

Если бы я был список списков, как следующее:

data_small = [ ['a','b','c'], ['d','e','f'] ] 
data_big = [ ['a','b','c'], ['d','e','f'], ['u','v','w'], ['x','y','z'] ] 

Как я могу получить список списков со всеми комбинациями? Для data_small это должно быть:

[ [a,b,c], [d,b,c], [a,b,f], [a,e,c], 
    [d,e,c], [d,b,f], [a,e,f], [d,e,f], ... ] 

Это также должно работать для произвольного числа списков той же длины, какdata_big.

Я уверен, что для этого есть причудливое решение itertools, правильно?

+0

Будут ли буквы в разных подсписках всегда уникальными? – gtlambert

+3

Технические характеристики неясны. Определите комбинацию. – timgeb

+1

Должно быть 20 комбинаций, и вы указали только 8, чтобы список либо не был полным, либо есть правила, которые не указаны. Что он? – SirParselot

ответ

2

Я думаю, что я расшифровал вопрос:

def so_called_combs(data): 
    for sublist in data: 
     for sbl in data: 
      if sbl==sublist: 
       yield sbl 
       continue 
      for i in range(len(sublist)): 
       c = sublist[:] 
       c[i] = sbl[i] 
       yield c 

Это возвращает необходимый список, если я правильно понял:

Для каждого списка в данных, каждый элемент заменяется (но только один в время) с соответствующим элементом (в том же положении) в каждом из других списков.

Для data_big, это возвращает:

[['a', 'b', 'c'], ['d', 'b', 'c'], ['a', 'e', 'c'], ['a', 'b', 'f'], 
['u', 'b', 'c'], ['a', 'v', 'c'], ['a', 'b', 'w'], ['x', 'b', 'c'], 
['a', 'y', 'c'], ['a', 'b', 'z'], ['a', 'e', 'f'], ['d', 'b', 'f'], 
['d', 'e', 'c'], ['d', 'e', 'f'], ['u', 'e', 'f'], ['d', 'v', 'f'], 
['d', 'e', 'w'], ['x', 'e', 'f'], ['d', 'y', 'f'], ['d', 'e', 'z'], 
['a', 'v', 'w'], ['u', 'b', 'w'], ['u', 'v', 'c'], ['d', 'v', 'w'], 
['u', 'e', 'w'], ['u', 'v', 'f'], ['u', 'v', 'w'], ['x', 'v', 'w'], 
['u', 'y', 'w'], ['u', 'v', 'z'], ['a', 'y', 'z'], ['x', 'b', 'z'], 
['x', 'y', 'c'], ['d', 'y', 'z'], ['x', 'e', 'z'], ['x', 'y', 'f'], 
['u', 'y', 'z'], ['x', 'v', 'z'], ['x', 'y', 'w'], ['x', 'y', 'z']] 
+0

Спасибо за это решение! "so_called_combs": D Как бы вы это назвали? – coroner

+0

@coroner Я не знаю, для чего вы его используете? Я бы не назвал его комбинациями, потому что это означает что-то другое (см. 'Itertools.combinations') – L3viathan

+0

Это не дает всех« комбинаций », в которых отсутствует« ['a', 'e', ​​'w'] 'и 23 more – SirParselot

1

Вот еще один способ сделать с помощью itertools перестановки и функции цепи. Кроме того, необходимо проверить, если индексы выстраиваются и все той же длины, и есть ли более чем один элемент заменяется

from itertools import * 
data_small = [ ['a','b','c'], ['d','e','f'] ] 
data_big = [ ['a','b','c'], ['d','e','f'], ['u','v','w'], ['x','y','z'] ] 

def check(data, sub): 
    check_for_mul_repl = [] 
    for i in data: 
     if len(i) != len(data[0]): 
      return False 

     for j in i: 
      if j in sub: 
       if i.index(j) != sub.index(j): 
        return False 
       else: 
        if i not in check_for_mul_repl: 
         check_for_mul_repl.append(i) 
    if len(check_for_mul_repl) <= 2: 
     return True 
print [x for x in list(permutations(chain(*data_big), 3)) if check(data_big, x)] 

['a', 'b', 'c'], ['a', 'b', 'f'], ['a', 'b', 'w'], ['a', 'b', 'z'], 
['a', 'e', 'c'], ['a', 'e', 'f'], ['a', 'v', 'c'], ['a', 'v', 'w'], 
['a', 'y', 'c'], ['a', 'y', 'z'], ['d', 'b', 'c'], ['d', 'b', 'f'], 
['d', 'e', 'c'], ['d', 'e', 'f'], ['d', 'e', 'w'], ['d', 'e', 'z'], 
['d', 'v', 'f'], ['d', 'v', 'w'], ['d', 'y', 'f'], ['d', 'y', 'z'], 
['u', 'b', 'c'], ['u', 'b', 'w'], ['u', 'e', 'f'], ['u', 'e', 'w'], 
['u', 'v', 'c'], ['u', 'v', 'f'], ['u', 'v', 'w'], ['u', 'v', 'z'], 
['u', 'y', 'w'], ['u', 'y', 'z'], ['x', 'b', 'c'], ['x', 'b', 'z'], 
['x', 'e', 'f'], ['x', 'e', 'z'], ['x', 'v', 'w'], ['x', 'v', 'z'], 
['x', 'y', 'c'], ['x', 'y', 'f'], ['x', 'y', 'w'], ['x', 'y', 'z'] 

Это не волнует, если есть более чем один элемент заменяется

from itertools import permutations, chain 

data_small = [ ['a','b','c'], ['d','e','f'] ] 
data_big = [ ['a','b','c'], ['d','e','f'], ['u','v','w'], ['x','y','z'] ] 

def check(data, sub): 
    for i in data: 
     if len(i) != len(data[0]): 
      return False 

     for j in i: 
      if j in sub: 
       if i.index(j) != sub.index(j): 
        return False 

    return True 

#If you really want lists just change the first x to list(x) 
print [x for x in list(permutations(chain(*data_big), 3)) if check(data_big, x)] 

['a', 'b', 'c'], ['a', 'b', 'f'], ['a', 'b', 'w'], 61 more... 

причина я использую перестановкам вместо комбинаций потому ('d','b','c') равно ('c','b','d') в терминах комбинаций и перестановок не

Если вы просто хотите комбинации, то это намного проще. Вы можете просто сделать

def check(data) #Check if all sub lists are same length 
    for i in data: 
     if len(i) != len(data[0]): 
      return False 
    return True 

if check(data_small): 
    print list(combinations(chain(*data_small), 3)) 

[('a', 'b', 'c'), ('a', 'b', 'd'), ('a', 'b', 'e'), ('a', 'b', 'f'), 
('a', 'c', 'd'), ('a', 'c', 'e'), ('a', 'c', 'f'), ('a', 'd', 'e'), 
('a', 'd', 'f'), ('a', 'e', 'f'), ('b', 'c', 'd'), ('b', 'c', 'e'), 
('b', 'c', 'f'), ('b', 'd', 'e'), ('b', 'd', 'f'), ('b', 'e', 'f'), 
('c', 'd', 'e'), ('c', 'd', 'f'), ('c', 'e', 'f'), ('d', 'e', 'f')] 
0

Извините за опоздание на партию, а вот фантазии «один - лайнер» (разделенный на несколько строк для удобства чтения) с использованием itertools и чрезвычайно полезный новый Python 3,5 распаковка обобщения (который, кстати, является значительно более быстрым и более удобным для чтения способом преобразования между типами итерации, чем, скажем, называя list явно) --- и предполагая уникальные элементы:

>>> from itertools import permutations, repeat, chain 
>>> next([*map(lambda m: [m[i][i] for i in range(a)], 
       {*permutations((*chain(*map(
        repeat, map(tuple, l), repeat(a - 1))),), a)})] 
     for l in ([['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i']],) 
     for a in (len(l[0]),)) 
[['g', 'h', 'f'], ['g', 'b', 'i'], ['g', 'b', 'f'], 
['d', 'b', 'f'], ['d', 'h', 'f'], ['d', 'h', 'i'], 
['a', 'e', 'c'], ['g', 'e', 'i'], ['a', 'h', 'i'], 
['a', 'e', 'f'], ['g', 'e', 'c'], ['a', 'b', 'i'], 
['g', 'b', 'c'], ['g', 'h', 'c'], ['d', 'h', 'c'], 
['d', 'b', 'c'], ['d', 'e', 'c'], ['a', 'b', 'f'], 
['d', 'b', 'i'], ['a', 'h', 'c'], ['g', 'e', 'f'], 
['a', 'e', 'i'], ['d', 'e', 'i'], ['a', 'h', 'f']] 

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

EDIT Я просто понял, что, возможно, мне следует дать краткое объяснение.Таким образом, внутренняя часть создает a - 1 копии каждого подсписщика (преобразуется в кортежи для проверки на хэшируемость и уникальность) и объединяет их вместе, чтобы позволить делать свою магию, чтобы создать все перестановки подписок a подписок. Затем они преобразуются в набор, который избавляется от всех дубликатов, которые должны произойти, а затем карта вытаскивает i-й элемент из i-го подсписок в каждой уникальной перестановке. Наконец, a - это длина первого подсписника, так как предполагается, что все подсписки имеют одинаковую длину.

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