Reputation: 1049
I have a tuple of tuples (Name, val 1, val 2, Class)
tuple = (("Jackson",10,12,"A"),
("Ryan",10,20,"A"),
("Michael",10,12,"B"),
("Andrew",10,20,"B"),
("McKensie",10,12,"C"),
("Alex",10,20,"D"))
I need to return all combinations using itertools combinations that do not repeat classes. How can I return combinations that dont repeat classes. For example, the first returned statement would be: tuple0, tuple2, tuple4, tuple5
and so on.
Upvotes: 0
Views: 156
Reputation: 368954
Make a group (by class):
>>> ts = (("Jackson",10,12,"A"),
... ("Ryan",10,20,"A"),
... ("Michael",10,12,"B"),
... ("Andrew",10,20,"B"),
... ("McKensie",10,12,"C"),
... ("Alex",10,20,"D"))
>>> import itertools
>>> import operator
>>>
>>> by_class = operator.itemgetter(3)
>>>
>>> tuple_grps = [list(grp) for key, grp in itertools.groupby(sorted(ts, key=by_class), key=by_class)]
>>> tuple_grps
[[('Jackson', 10, 12, 'A'), ('Ryan', 10, 20, 'A')],
[('Michael', 10, 12, 'B'), ('Andrew', 10, 20, 'B')],
[('McKensie', 10, 12, 'C')],
[('Alex', 10, 20, 'D')]]
Then, use itertools.product
to get the desired results:
>>> for xs in itertools.product(*tuple_grps):
... print(xs)
...
(('Jackson', 10, 12, 'A'), ('Michael', 10, 12, 'B'), ('McKensie', 10, 12, 'C'), ('Alex', 10, 20, 'D'))
(('Jackson', 10, 12, 'A'), ('Andrew', 10, 20, 'B'), ('McKensie', 10, 12, 'C'), ('Alex', 10, 20, 'D'))
(('Ryan', 10, 20, 'A'), ('Michael', 10, 12, 'B'), ('McKensie', 10, 12, 'C'), ('Alex', 10, 20, 'D'))
(('Ryan', 10, 20, 'A'), ('Andrew', 10, 20, 'B'), ('McKensie', 10, 12, 'C'), ('Alex', 10, 20, 'D'))
To get any length of combinations:
>>> for i in range(1, len(tuple_grps)+1):
... for xs in itertools.combinations(tuple_grps, i):
... for ys in itertools.product(*xs):
... print(ys)
...
(('Jackson', 10, 12, 'A'),)
(('Ryan', 10, 20, 'A'),)
(('Michael', 10, 12, 'B'),)
(('Andrew', 10, 20, 'B'),)
(('McKensie', 10, 12, 'C'),)
(('Alex', 10, 20, 'D'),)
(('Jackson', 10, 12, 'A'), ('Michael', 10, 12, 'B'))
(('Jackson', 10, 12, 'A'), ('Andrew', 10, 20, 'B'))
(('Ryan', 10, 20, 'A'), ('Michael', 10, 12, 'B'))
(('Ryan', 10, 20, 'A'), ('Andrew', 10, 20, 'B'))
...
(('Ryan', 10, 20, 'A'), ('Andrew', 10, 20, 'B'), ('McKensie', 10, 12, 'C'), ('Alex', 10, 20, 'D'))
Upvotes: 5