Reputation: 353
I wonder if someone can help with the following task: What is the way to get all combinations a list can be split into sublists, when order does not matter?
Let's say I have a list of 4 items:
import itertools as it
a = [1, 2, 3, 4]
print(list(it.combinations(a, 2)))
That will give me a list of 6 possible pairs:
[(1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4)]
How to make (out of it? or any other way) a set of lists that contain original [1, 2, 3, 4]
sequence in any order? So for this example it will contain three sublists:
[(1, 2), (3, 4)]
[(1, 3), (2, 4)]
[(1, 4), (2, 3)]
UPDATE:
A small clarification:
In other words, I need to get all sets of n-tuples such that their members contain all the population of original list, when the order within an n-tuple does not matter. Thus [(1, 2), (3, 4)]
is ok, but [(2, 1), (3, 4)]
is not needed because it is the same as the first set, if we ignore the order.
UPDATE2:
So for the list of length 6, and for chunks of size 2 this fun
function should work as follows:
import itertools as it
a = [1, 2, 3, 4, 5, 6,]
r = 2
# fun(a,r):
# OUT:
# [
# (1, 2), (3, 4), (5, 6)
# (1, 3), (2, 4), (5, 6),
# (1, 4), (2, 3), (5, 6),
# (1, 5), (2, 3), (4, 6),
# (1, 6), (2, 3), (4, 5),
# ]
Upvotes: 6
Views: 2040
Reputation: 282
a = [1, 2, 3, 4]
choices = []
for i in range(len(a)):
for j in range(i+1, len(a)):
sub_a1 = (a[i], a[j])
sub_a2 = tuple(j for j in a if j not in sub_a1)
sub_a = sorted([sub_a1, sub_a2])
if sub_a not in choices:
choices.append(sub_a)
for k in choices:
print(k)
May be this code can help your requirements.
Upvotes: 0
Reputation: 3801
As you require the "remainder" of what is in a
, you can use a set
difference
In [901]: [(c, tuple(set(a) - set(c))) for c in it.combinations(a, 2)]
Out[901]:
[((1, 2), (3, 4)),
((1, 3), (2, 4)),
((1, 4), (2, 3)),
((2, 3), (1, 4)),
((2, 4), (1, 3)),
((3, 4), (1, 2))]
However, this gives you twice as many results as you require so to eliminate these duplicates we need to sort and set
ify the result set which will give us a set of list
s which can't be turned into set
s. You should then cast the list
s to tuple
s.
In [900]: {tuple(sorted((c, tuple(set(a) - set(c))))) for c in it.combinations(a, 2)}
Out[900]: {((1, 2), (3, 4)), ((1, 3), (2, 4)), ((1, 4), (2, 3))}
If you require a list
of list
of tuple
then you can use the following
In [902]: s = {tuple(sorted((c, tuple(set_a - set(c))))) for c in it.combinations(a, 2)}
In [903]: [list(l) for l in s]
Out[903]: [[(1, 3), (2, 4)], [(1, 4), (2, 3)], [(1, 2), (3, 4)]]
Upvotes: 0
Reputation: 12025
Just zip
the combinations, with its reverse and take only the first half of the resulting list
>>> import itertools as it
>>> lst = [1, 2, 3, 4]
>>> r = len(lst)//2
>>> combs = list(it.combinations(lst, r))
>>> list(it.islice(zip(combs, reversed(combs)), len(combs)//2))
[((1, 2), (3, 4)), ((1, 3), (2, 4)), ((1, 4), (2, 3))]
Upvotes: 2