Удаление дубликатов списков списков - PullRequest
0 голосов
/ 07 мая 2018

Я хочу написать скрипт, который будет принимать список категорий и возвращать уникальные способы разделения категорий на 2 группы. Пока у меня есть это в форме кортежа (list_a, list_b), где объединение list_a и list_b представляет полный список категорий.

Ниже я показал пример с категориями ['A', 'B', 'C', 'D'], я могу получить все группы. Тем не менее, некоторые дубликаты (['A'], ['B', 'C', 'D']) представляют то же разделение, что и (['B', 'C', 'D'], ['A' ]). Как сохранить только уникальные сплиты? И какой заголовок лучше для этого поста?

import itertools
def getCompliment(smallList, fullList):
    compliment = list()
    for item in fullList:
        if item not in smallList:
            compliment.append(item)
    return compliment

optionList = ['A','B','C','D']
combos = list()
for r in range(1,len(optionList)):
    tuples = list(itertools.combinations(optionList, r))
    for t in tuples:
        combos.append((list(t),getCompliment(list(t), optionList)))

print(combos)

[(['A'], ['B', 'C', 'D']),
 (['B'], ['A', 'C', 'D']), 
 (['C'], ['A', 'B', 'D']),
 (['D'], ['A', 'B', 'C']),
 (['A', 'B'], ['C', 'D']),
 (['A', 'C'], ['B', 'D']),
 (['A', 'D'], ['B', 'C']),
 (['B', 'C'], ['A', 'D']),
 (['B', 'D'], ['A', 'C']),
 (['C', 'D'], ['A', 'B']),
 (['A', 'B', 'C'], ['D']),
 (['A', 'B', 'D'], ['C']),
 (['A', 'C', 'D'], ['B']),
 (['B', 'C', 'D'], ['A'])]

Мне нужно следующее:

[(['A'], ['B', 'C', 'D']),
 (['B'], ['A', 'C', 'D']), 
 (['C'], ['A', 'B', 'D']),
 (['D'], ['A', 'B', 'C']),
 (['A', 'B'], ['C', 'D']),
 (['A', 'C'], ['B', 'D']),
 (['A', 'D'], ['B', 'C'])]

1 Ответ

0 голосов
/ 07 мая 2018

Вы очень близки. Вам нужно set результатов.

Поскольку элементы set должны быть хэшируемыми, а объекты list не являются хэшируемыми, вместо них можно использовать tuple. Это может быть достигнуто некоторыми тривиальными изменениями в вашем коде.

import itertools

def getCompliment(smallList, fullList):
    compliment = list()
    for item in fullList:
        if item not in smallList:
            compliment.append(item)
    return tuple(compliment)

optionList = ('A','B','C','D')
combos = set()
for r in range(1,len(optionList)):
    tuples = list(itertools.combinations(optionList, r))
    for t in tuples:
        combos.add(frozenset((tuple(t), getCompliment(tuple(t), optionList))))

print(combos)

{frozenset({('A',), ('B', 'C', 'D')}),
 frozenset({('A', 'C', 'D'), ('B',)}),
 frozenset({('A', 'B', 'D'), ('C',)}),
 frozenset({('A', 'B'), ('C', 'D')}),
 frozenset({('A', 'C'), ('B', 'D')}),
 frozenset({('A', 'D'), ('B', 'C')}),
 frozenset({('A', 'B', 'C'), ('D',)})}

Если вам нужно преобразовать результат обратно в список списков, это возможно через понимание списка:

res = [list(map(list, i)) for i in combos]

[[['A'], ['B', 'C', 'D']],
 [['B'], ['A', 'C', 'D']],
 [['A', 'B', 'D'], ['C']],
 [['A', 'B'], ['C', 'D']],
 [['B', 'D'], ['A', 'C']],
 [['B', 'C'], ['A', 'D']],
 [['A', 'B', 'C'], ['D']]]
...