Reputation: 428
I am using for num in combinations(nums[0], number):
to return all combinations of numbers in a list, where num = len(nums[0])-1
.
What I would like to do is return, as a separate variable, the value of the list item that is not used in each combination, so for example if nums[1,2,3]
then I would want it to return:
[1,2],[3]
[1,3],[2]
[2,3],[1]
Please tell me if this is unclear. I feel like this is probably some basic python fundamentals but I can't figure out how to do it. Thank you for any help.
Upvotes: 1
Views: 397
Reputation: 31329
Since your list can have duplicates:
from itertools import combinations
nums = [1, 2, 3, 3]
# get combinations of all possible lengths
combos = []
for n in range(len(nums)):
combos += combinations(nums, n)
# create the pairs you want, but with all nums
combo_pairs = [(combo, list(nums)) for combo in combos]
# remove the nums that are in the combination for each pair
for combo, combo_nums in combo_pairs:
for n in combo:
combo_nums.remove(n)
print(combo_pairs)
Note: this will cause duplicates for duplicate values (one for the one three, one for the other). You can get rid of those like this:
combo_pairs = list(set([(combo, tuple(combo_nums)) for combo, combo_nums in combo_pairs]))
That turns the nums in the pair into a tuple, since a tuple is hashable, but a list isn't. You can always convert back to a list, if you need to of course.
If you're only interested in combinations that have a length that's one less than the original, you can do this:
from itertools import combinations
nums = [1, 2, 3, 3]
# get combinations of correct length
combos = combinations(nums, len(nums)-1)
# create the pairs you want, but with all nums
combo_pairs = [(combo, list(nums)) for combo in combos]
# remove the nums that are in the combination for each pair
for combo, combo_nums in combo_pairs:
for n in combo:
combo_nums.remove(n)
print(combo_pairs)
But in that case, you may as well:
nums = [1, 2, 3, 3]
combos = [(nums[:n] + nums[n+1:], [nums[n]]) for n in range(len(nums))]
Upvotes: 3
Reputation: 51063
Since the rest of the combination is uniquely determined by which element is "left out", you don't really need itertools for this.
def combinations_leaving_one_out(lst):
lst = sorted(lst)
prev_x = None
for i, x in enumerate(lst):
if x != prev_x:
yield tuple(lst[:i] + lst[i+1:]), x
prev_x = x
Example:
>>> lst = [1, 2, 3, 1, 2, 4]
>>> for comb, left_out in combinations_leaving_one_out(lst):
... print(comb, left_out)
...
(1, 2, 2, 3, 4) 1
(1, 1, 2, 3, 4) 2
(1, 1, 2, 2, 4) 3
(1, 1, 2, 2, 3) 4
Upvotes: 0