'How to get multiple combinations of multiple lists in python (Multiple n Choose K or nCr)
I have been looking on google and stack overflow for a few hours and I am sure there is an answer for what this is mathematically or perhaps it is just what the calculation is, which would be (nCr * nCr * nCr etc.,) combinations of multiple groups.
However, to phrase what I am trying to do in Python: I am trying to find all combinations of a list of multiple lists and iterate through all those combinations.(I have been struggling with how to phrase it, see below for a visual)
I have figured out if I want to pick one item from each list, total of 4 items, print all 4 item combinations.
This code I have works for that first part:
a = [[1,2,3,4,5],[6,7,8,9],[10,11,12,13,14],[15,16,17,18,19]]
r=[[]]
for x in a:
t = []
for y in x:
for i in r:
t.append(i+[y])
r = t
print (r)
Output:
[[1, 6, 10, 15],
[2, 6, 10, 15],
[3, 6, 10, 15],
[4, 6, 10, 15],
[5, 6, 10, 15],...
Which is exactly what I am trying to do, I want to select an item from these 4 lists and see all combinations, which this does. Great!
However, I want to scale this and I cannot figure out how, for example, pick 2 items from each list, and display all combinations.
So for this code to output something like this instead:
Output:
[[[1, 2],[7,9],[10,14],[15,19]] ,
[[1, 3],[7,9],[10,14],[15,19]] ,
[[1, 4],[7,9],[10,14],[15,19]]....
What modifications to my python code above to do I need to make, to get this output.
Let me know if you need additional information, the question is just hard to phrase without sounding redundant.
Solution 1:[1]
The factorial increase in this problem might cause some memory problems even for small lists. That's being said, here is my approach to this problem:
- Let list
a = [a_1, a_2, ..., a_p]
. Each element (a_i
) is also a list. I will take thek
combinations of each element ina
and call itZ
Z = [C(a_1,k), C(a_2,k), ..., C(a_p, k)]
- Then
Z[C(a_1,k)[0], C(a_2,k)[0], ..., C(a_3,k)[0]]
will give me the first combination of the combinations. - I will iterate over combinations of combinations until no combinations left.
Here is an example:
a = [[1,2,3], [4,5,6]]
andk=2
(choosek
)Z = [[(1, 2), (1, 3), (2, 3)], [(4, 5), (4, 6), (5, 6)]]
- Then the first combination of combinations will be
[(1,2), (4,5)]
- Second combination of combinations will be
[(1,2), (4,6)]
- I will iterate over all 9 combination of combinations.
Here is the class for the python:
class Comb_k:
def __init__(self, a, k):
self.Z = [list(combinations(i, k)) for i in a] # k combinations of each list inside a
self.ns = [len(i)-1 for i in self.Z] # length of the each combination in Z
self.p = len(a) # length of a
self.pos = self.p*[0] # I will keep track of which combination in each will be returned
self.pos[-1] = -1 # I will increase the combination index for each return
def __iter__(self):
return self
def __next__(self):
Z = self.Z
p = self.p
self.pos = self.next_i()
return [z[c] for z,c in zip(Z, self.pos)]
def next_i(self):
'''
This will iterate the next combination
'''
pos = self.pos
ns = self.ns
p = self.p
for i in range(p-1, -1, -1):
c = pos[i]
n = ns[i]
if c == n:
pos[i] = 0
else:
pos[i] += 1
return pos
raise GeneratorExit('End of the Combinations')
a = [[1,2,3], [4,5,6]]
comb_k = Comb_k(a, k = 2)
[next(comb_k) for _ in range(9)] # (3 choose 2)x(3 choose 2) = 9
This will return the following list:
[[(1, 2), (4, 5)],
[(1, 2), (4, 6)],
[(1, 2), (5, 6)],
[(1, 3), (4, 5)],
[(1, 3), (4, 6)],
[(1, 3), (5, 6)],
[(2, 3), (4, 5)],
[(2, 3), (4, 6)],
[(2, 3), (5, 6)]]
For convenience, the class is a generator, so it is not returning the all combinations at once.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 |