Search code examples
pythoncombinationspython-itertools

Itertools Combinations No Repeats: Where rgb is equivelant to rbg etc


I'm trying to use itertools.combinations to return unique combinations. I've searched through several similar questions but have not been able to find an answer.

An example:

>>> import itertools
>>> e = ['r','g','b','g']
>>> list(itertools.combinations(e,3))
[('r', 'g', 'b'), ('r', 'g', 'g'), ('r', 'b', 'g'), ('g', 'b', 'g')]

For my purposes, (r,g,b) is identical to (r,b,g) and so I would want to return only (rgb),(rgg) and (gbg).

This is just an illustrative example and I would want to ignore all such 'duplicates'. The list e could contain up to 5 elements. Each individual element would be either r, g or b. Always looking for combinations of 3 elements from e.

To be concrete, the following are the only combinations I wish to call 'valid': (rrr), (ggg), (bbb), (rgb).

So perhaps the question boils down to how to treat any variation of (rgb) as equal to (rgb) and therefore ignore it.

Can I use itertools to achieve this or do I need to write my own code to drop the 'dupliates' here? If no itertools solution then I can just easily check if each is a variation of (rgb), but this feels a bit 'un-pythonic'.


Solution

  • According to your definition of "valid outputs", you can directly build them like this:

    from collections import Counter
    
    # Your distinct values
    values = ['r', 'g', 'b']
    
    e = ['r','g','b','g', 'g']
    
    count = Counter(e)
    # Counter({'g': 3, 'r': 1, 'b': 1})
    
    # If x appears at least 3 times, 'xxx' is a valid combination  
    combinations = [x*3 for x in values if count[x] >=3]
    
    # If all values appear at least once, 'rgb' is a valid combination
    if all([count[x]>=1 for x in values]):
        combinations.append('rgb')
    
    print(combinations)
    #['ggg', 'rgb']
    

    This will be more efficient than creating all possible combinations and filtering the valid ones afterwards.