2
import itertools
a = [[2, 3], [3, 4]]
b = [[5, 6], [7, 8], [9, 10]]
c = [[11, 12], [13, 14]]
d = [[15, 16], [17, 18]]
e = [[12,16],[13,17],[14,18],[15,19]]

q=[]
q=list(itertools.combinations((a, b, b,c, c, d,e),7)
print q

How would I go about using the combination function from itertools properly to use list a one time, b 2 times without replacement, c 2 times without replacement, and d and e one time each?

[[[2, 3],[5, 6],[7, 8],[11, 12],[13, 14],[15, 16],[12,16]], 
[[2, 3],[5, 6],[7, 8],[11, 12],[13, 14],[15, 16],[13,17]],
[[2, 3],[5, 6],[7, 8],[11, 12],[13, 14],[15, 16],[14,18]],
[[2, 3],[5, 6],[7, 8],[11, 12],[13, 14],[15, 16],[15,19]], 
[[2, 3],[5, 6],[7, 8],[11, 12],[13, 14],[15, 16],[12,16]],...
[[3, 4],[7, 8],[9, 10],[11, 12], [13, 14],[17, 18],[15,19]]]
4
  • 1
    Are the two draws from b with or without replacement? Commented Sep 15, 2016 at 20:35
  • 1
    I'm not sure I understand what you want here (can you give the first few example outputs or something to be sure?), but if you wrap itertools.combinations in list for a decent number of inputs, you're almost guaranteed to blow your memory. The number of outputs grows at roughly O(n!) (factorial growth); you're usually expected to iterate the combinations one by one, not store them all at once. Commented Sep 15, 2016 at 20:35
  • Without replacement, Commented Sep 15, 2016 at 20:39
  • 1
    Could you show us the expected output? Commented Sep 15, 2016 at 20:46

3 Answers 3

1

It seems like you are looking for a combination of combinations and product: Use combinations to get the possible combinations without replacement for the repeated lists, then use product to combine all those combinations. You can put the lists and counts in two lists, zip those lists, and use a generator expression to get all the combinations.

from itertools import product, combinations, chain
lists = [a,b,c,d,e]
counts = [1,2,2,1,1]
combs = product(*(combinations(l, c) for l, c in zip(lists, counts)))

For this example, the combs generator has 48 elements, among others:

[(([2, 3],), ([5, 6], [7, 8]), ([11, 12], [13, 14]), ([15, 16],), ([12, 16],)),
 ...
 (([2, 3],), ([5, 6], [7, 8]), ([11, 12], [13, 14]), ([17, 18],), ([15, 19],)),
 (([2, 3],), ([5, 6], [9, 10]),([11, 12], [13, 14]), ([15, 16],), ([12, 16],)),
 ...
 (([3, 4],), ([5, 6], [7, 8]), ([11, 12], [13, 14]), ([15, 16],), ([12, 16],)),
 ...
 (([3, 4],), ([5, 6], [7, 8]), ([11, 12], [13, 14]), ([17, 18],), ([15, 19],)),
 ...
 (([3, 4],), ([7, 8], [9, 10]),([11, 12], [13, 14]), ([17, 18],), ([15, 19],))]

If you want flattened lists, just chain them:

>>> combs = (list(chain(*p)) for p in product(*(combinations(l, c) for l, c in zip(lists, counts))))
>>> list(combs)
[[[2, 3], [5, 6], [7, 8], [11, 12], [13, 14], [15, 16], [12, 16]],
 ...
 [[3, 4], [7, 8], [9, 10], [11, 12], [13, 14], [17, 18], [15, 19]]]
Sign up to request clarification or add additional context in comments.

Comments

1

What your are trying to achieve is the Cartesian product of input iterables and not the combinations of the item present in the list. Hence you have to use itertools.product() instead.

In case repetition is allowed among the lists which used more than once, answer is simple:

>>> import itertools
>>> a = [1,2]
>>> b = [3,4]
>>> [i for i in itertools.product(a, b, b)]
[(1, 3, 3), (1, 3, 4), (1, 4, 3), (1, 4, 4), (2, 3, 3), (2, 3, 4), (2, 4, 3), (2, 4, 4)]

But in case repetition is not allowed within the same lists, it will become little nasty and you need to combine the above answer with combinations() and chain() (same as mentioned by tobias_k). This code will give the list of all combinations:

>>> from itertools import chain, product, combinations
>>> lists, counts = [a, b], [1, 2]  # to track that a is to be used once, and b twice
>>> list(list(chain(*p)) for p in product(*(combinations(l, c) for l, c in zip(lists, counts))))
[[1, 3, 4], [2, 3, 4]]

However, in case you need permutations instead of combinations, you have to update the above code with permutations():

>>> from itertools import chain, product, permutations
>>> list(list(chain(*p)) for p in product(*(permutations(l, c) for l, c in zip(lists, counts))))
[[1, 3, 4], [1, 4, 3], [2, 3, 4], [2, 4, 3]]

6 Comments

Not entirely clear from the question, but I think then the last line in the expected output should contain [13, 14], [11, 12] instead of [11, 12], [13, 14].
@tobias_k On looking at his sample output, I believe he needs cartesian product of the lists. Updated the answer with simple example. And I agree with you, the input params OP provided are too huge and gives no clear insight of his intention. Simpler example would be helpful
order doesnt matter
@WilliamBernard : In that case it is @ tobias_k answer you should be marked as accepted. As I have mentioned this after he answered
@WilliamBernard: It was not cleared from the sample you provided in the question. So, I mentioned all the possible solutions :P
|
1

Updated given clarification of expected output:

You want itertools.product:

itertools.product(a, b, b, c, c, c, c, d, e)

Which will pick one element from each of its arguments on each iteration, cycling the rightmost element the fastest, leftmost slowest.

You can use extended argument unpacking to express the repetition of certain arguments a little more obviously in Python 3:

itertools.product(a, *[b]*2, *[c]*4, d, e)

Or use tobias_k's solution for more general repetition of sequences (that will also work on Py2).

2 Comments

But this will not draw one from a, two from b, etc., but just 9 from all together.
@tobias_k: I answered before the OP clarified the precise usage. Will fix.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.