Search code examples
pythoncombinationsnested-listspython-itertools

Exhaustive combinations of lists in python


I have a long list of lists in Python that looks something like this:

myList=[

('a',[1,2,3,4,5]),
('b',[6,7,8,9,10]),
('c',[1,3,5,7,9]),
('d',[2,4,6,8,10]),
('e',[4,5,6,7,8])

]

And I would like to enumerate the common values exhaustively

('a:b', ),
('a:c', [1,3,5]),
('a:d', [2,4]),
('a:e', [4,5]),
('b:c', [7,9]),
('b:d', [6,8,10]),

('a:c:e', [5]),
('b:c:e', [7]),
('b:d:e', [6,8]),

and the same for groups of four, five, six until all common values have been identified (assuming the lists were longer)

Is this possible using the itertools library or sets or a combination of the above?

I have been trying to write a function that loops over the original list for every new list I generate but It hasn't been going well!

Here is what I have:

def findCommonElements(MyList):

    def sets(items):
        for name, tuple in items:
            yield name, set(tuple)

    def matches(sets):
       for a, b in combinations(sets, 2):
           yield ':'.join([a[0], b[0]]), a[1] & b[1]

    combinationsSet=list(matches(sets(keywordCount)))

    combinationsList=[]
    for pair,tup in combinationsSet:
        setList=list(tup)
        combinationsList.append((pair, len(setList), setList))
    combinationsList=sorted(combinationsList,key=lambda x: x[1], reverse=True) #this just sorts the list by the number of common elements

    return combinationsList

Solution

  • I think You can try to use itertools.combinations with itertools.chain

    nit very good example but It should work. I will use itertools and generators here:

    lengthes = xrange(2, len(myList)+1)
    combinations_list = (itertools.combinations(myList, i) for i in lengthes)
    combinations = itertools.chain.from_iterable(combinations_list)
    def find_intersection(lists):
        res = set(lists[0])
        for data in lists:
            res &= set(data)
        return res
    result = [(':'.join(i), list(find_intersection(v))) for i, v in (zip(*x) for x in combinations)]
    

    or just itertools.combinations

    def findCommonElements(MyList):
    
        combinationsList=[]
    
        for seq_len in xrange(2, len(MyList)+1):
            for combination in combinations:
                for indexes, values in zip(*combination):
                    intersection = reduce(lambda x, y: x & set(y[1]), 
                                          values, set(values[0]))
                    if intersection:
                        combinationsList.appen(':'.join(indexes), intersection)
            return combinationsList