переставлять комбинации кортежей среди вложенного списка - PullRequest
0 голосов
/ 07 ноября 2018

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

test = [[('a',)],
        [('b', 'c'), ('d', 'e')],
        [('f', 'g'), ('h', 'i'), ('j', 'k')],
        [('l', 'm'), ('n', 'o'), ('p', 'q')]]

Мой ожидаемый результат такой:

[(('a',), ('b', 'c')),
 (('a',), ('d', 'e')),
 (('a',), ('f', 'g')),
 (('a',), ('h', 'i')),
 (('a',), ('j', 'k')),
 (('b', 'c'), ('f', 'g')),
 (('b', 'c'), ('h', 'i')),
 (('b', 'c'), ('j', 'k')),
 (('d', 'e'), ('f', 'g')),
 (('d', 'e'), ('h', 'i')),
 (('d', 'e'), ('j', 'k')),
 (('a',), ('b', 'c'), ('f', 'g')),
 (('a',), ('b', 'c'), ('h', 'i')),
 (('a',), ('b', 'c'), ('j', 'k')),
 (('a',), ('d', 'e'), ('f', 'g')),...,
 (('a',), ('b', 'c'), ('f', 'g'), ('l', 'm')), ...]

Для дальнейшего уточнения моей конечной целью является перестановка среди списков кортежей от перестановки 2 до перестановки произведений с той же логикой, что и самоперестановки нет. то есть, если во вложенном списке 5 подсписков, я переставлю комбинацию от 2 до 5. Примерно так: [((),()),...,((),(),()),...,((),(),(),()),...,((),(),(),(),()),...]

Я пробовал list(itertools.combinations(itertools.chain(*test),2)), но я не хочу перестановку среди подсписков. Например, я хочу исключить

((('b', 'c'), ('d', 'e')),
 (('f', 'g'), ('h', 'i')),
 (('f', 'g'), ('j', 'k')),
 (('h', 'i'), ('j', 'k')),
 (('f', 'g'), ('h', 'i'), ('j', 'k')),...)

1 Ответ

0 голосов
/ 07 ноября 2018

Вы можете использовать рекурсию:

test = [[('a',)],
    [('b', 'c'), ('d', 'e')],
    [('f', 'g'), ('h', 'i'), ('j', 'k')]] 

def _product(d):
   def combinations(d, _c = []):
      for i, a in enumerate(d):
        for c in a:
          if len(_c) == 1 and not any(all(t in h for t in _c+[c]) for h in d):
            yield tuple(sorted(_c+[c]))
          yield from combinations(d[1:], _c = [] if len(_c) > 0 else _c+[c])
   r = list(combinations(d))
   return [a for i, a in enumerate(r) if a not in r[:i]]

print(_product(test))

Выход:

[(('a',), ('b', 'c')), 
 (('a',), ('d', 'e')), 
 (('a',), ('f', 'g')), 
 (('a',), ('h', 'i')), 
 (('a',), ('j', 'k')), 
 (('b', 'c'), ('f', 'g')), 
 (('b', 'c'), ('h', 'i')), 
 (('b', 'c'), ('j', 'k')), 
 (('d', 'e'), ('f', 'g')), 
 (('d', 'e'), ('h', 'i')), 
 (('d', 'e'), ('j', 'k'))]

Редактировать

Чтобы найти все перестановки, создайте метод для поиска перестановок определенной длины, затем выполните итерации по диапазону ввода ввода и используйте представление списка для полного результата:

def product(d, _len):
  def combinations(d, _d, current):
    if len(current) == _d:
      yield tuple(sorted(current))
    else:
      if d:
        for i in d:
          for c in i:
            _c = current+[c]
            if not current or (not any(all(t in h for t in _c) for h in d) and len(set(_c))) == len(_c):
              yield from combinations(d, _d, _c)
  r = list(combinations(d, _len, []))
  return [a for i, a in enumerate(r) if a not in r[:i]]

def full_product(test):
  return [i for b in range(2, len(test)+1) for i in product(test, b)]

for i in full_product(test):
  print(i)

Выход:

(('a',), ('b', 'c'))
(('a',), ('d', 'e'))
(('a',), ('f', 'g'))
(('a',), ('h', 'i'))
(('a',), ('j', 'k'))
(('b', 'c'), ('f', 'g'))
(('b', 'c'), ('h', 'i'))
(('b', 'c'), ('j', 'k'))
(('d', 'e'), ('f', 'g'))
(('d', 'e'), ('h', 'i'))
(('d', 'e'), ('j', 'k'))
(('a',), ('b', 'c'), ('d', 'e'))
(('a',), ('b', 'c'), ('f', 'g'))
(('a',), ('b', 'c'), ('h', 'i'))
(('a',), ('b', 'c'), ('j', 'k'))
(('a',), ('d', 'e'), ('f', 'g'))
(('a',), ('d', 'e'), ('h', 'i'))
(('a',), ('d', 'e'), ('j', 'k'))
(('a',), ('f', 'g'), ('h', 'i'))
(('a',), ('f', 'g'), ('j', 'k'))
(('a',), ('h', 'i'), ('j', 'k'))
(('b', 'c'), ('d', 'e'), ('f', 'g'))
(('b', 'c'), ('f', 'g'), ('h', 'i'))
(('b', 'c'), ('f', 'g'), ('j', 'k'))
(('b', 'c'), ('d', 'e'), ('h', 'i'))
(('b', 'c'), ('h', 'i'), ('j', 'k'))
(('b', 'c'), ('d', 'e'), ('j', 'k'))
(('d', 'e'), ('f', 'g'), ('h', 'i'))
(('d', 'e'), ('f', 'g'), ('j', 'k'))
(('d', 'e'), ('h', 'i'), ('j', 'k'))

Редактировать 2: при запуске full_product в обновленной переменной test часть вывода при длине четыре равна:

...
(('a',), ('b', 'c'), ('d', 'e'), ('f', 'g'))
(('a',), ('b', 'c'), ('d', 'e'), ('h', 'i'))
(('a',), ('b', 'c'), ('d', 'e'), ('j', 'k'))
(('a',), ('b', 'c'), ('d', 'e'), ('l', 'm'))
(('a',), ('b', 'c'), ('d', 'e'), ('n', 'o'))
(('a',), ('b', 'c'), ('d', 'e'), ('p', 'q'))
...
...