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'.
According to your definition of "valid outputs", you can directly build them like this:
This will be more efficient than creating all possible combinations and filtering the valid ones afterwards.
You can use a
set
to discard duplicates.In your case the number of characters is the way you identify duplicates so you could use
collections.Counter
. In order to save them in aset
you need to convert them tofrozenset
s though (becauseCounter
isn't hashable):If you want to convert them to strings use:
and it will give:
The approach is a variation of the
unique_everseen
recipe (itertools module documentation) - so it's probably "quite pythonic".It is not completely clear what you want to return. It depends on what comes first when iterating. For example if
gbr
is found first, thenrgb
will be discarded as a duplicate:This would give you: