DeeeeRoy
DeeeeRoy

Reputation: 487

Deleting Duplicate Tuples of Lists from List

I want to write a script to take a list of categories and return the unique ways to split the categories into 2 groups. For now I have it in tuple form (list_a, list_b) where the union of list_a and list_b represents the full list of categories.

Below I have shown with an example with categories ['A','B','C','D'], I can get all the groups. However, some are duplicates (['A'], ['B', 'C', 'D']) represents the same split as (['B', 'C', 'D'], ['A']). How do I retain only unique splits? Also what is a better title for this post?

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'])]

I need the following:

[(['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'])]

Upvotes: 3

Views: 41

Answers (1)

jpp
jpp

Reputation: 164623

You are very close. What you need is a set of results.

Since set elements must be hashable and list objects are not hashable, you can use tuple instead. This can be achieved by some trivial changes to your code.

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',)})}

If you need to convert the result back to a list of lists, this is possible via a list comprehension:

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']]]

Upvotes: 3

Related Questions