Cole
Cole

Reputation: 2509

Python: how do I create a list of combinations from a series of ranges of numbers

For a list of numerical values of n length, e. g. [1, 3, 1, 2, ...], I would like to create a list of the lists of all possible combinations of values from range[x+1] where x is a value from the list. The output might look something like this:

for list[1, 3, 2] return all possible lists of range[x+1] values:
    # the sequence of the list is unimportant
[
[0,0,0],[1,0,0],[0,1,0],[0,2,0],[0,3,0],[0,0,1],[0,0,2],[1,1,0],
[1,2,0],[1,3,0],[1,0,1],[1,0,2],[0,1,1],[0,2,1],[0,3,1],[0,1,2],
[0,2,2],[0,3,2],[1,1,1],[1,2,1],[1,3,1],[1,1,2],[1,2,2],[1,3,2]
]

So in this example I am looking for all variations of [e1, e2, e3] from e1 in [0,1], e2 in [0,1,2,3] and e3 in [0,1,2]

Upvotes: 1

Views: 573

Answers (6)

boxmein
boxmein

Reputation: 875

Python's itertools module has a tool that does what you need:

import itertools
p = itertools.permutations([0, 1, 2, 3])
p_as_list = list(p)

Edit: As your needs are fairly specific you could benefit from having your own function that does something alike this one: (note I haven't got the implementation down just yet, maybe someone might refine this):

def magic_permutations (*args):
    lists = []
    larg = len(args)
    for i in range(larg):
        lists.append([])
    i = 0
    for nums in args: 
        for num in nums:
            if i >= larg:
                i = 0
            lists[i].append(num)
            i += 1
    return lists

Edit: I misunderstood your question the first time, so I'll apologize for that. I'll however leave this be.

Upvotes: 5

CT Zhu
CT Zhu

Reputation: 54330

Using numpy if you don't mind getting tuples in the end:

>>> import numpy as np
>>> e1=np.array([0,1])
>>> e2=np.array([0,1,2])
>>> e3=np.array([0,1,2,3])
>>> g=np.meshgrid(e1,e2,e3) #you need numpy ver>1.7.0, change the order of final result by changing the order of e1, e2, e3
>>> zip(*[item.flatten() for item in g])
[(0, 0, 0), (0, 0, 1), (0, 0, 2), (0, 0, 3), (1, 0, 0), (1, 0, 1), (1, 0, 2), (1, 0, 3), (0, 1, 0), (0, 1, 1), (0, 1, 2), (0, 1, 3), (1, 1, 0), (1, 1, 1), (1, 1, 2), (1, 1, 3), (0, 2, 0), (0, 2, 1), (0, 2, 2), (0, 2, 3), (1, 2, 0), (1, 2, 1), (1, 2, 2), (1, 2, 3)]

Upvotes: 1

Akinakes
Akinakes

Reputation: 657

It's not in the same order, but I think this is what you wanted:

def xrangeCombinations(input):
    if len(input) > 1:
        for i in xrange(input[-1] + 1):
            for j in xrangeCombinations(input[:-1]):
                yield j + [i]
    else:
        for i in xrange(input[-1] + 1):
            yield [i]

for i in xrangeCombinations([1, 3, 2]):
    print i

Produces the output:

[0, 0, 0]
[1, 0, 0]
[0, 1, 0]
[1, 1, 0]
[0, 2, 0]
[1, 2, 0]
[0, 3, 0]
[1, 3, 0]
[0, 0, 1]
[1, 0, 1]
[0, 1, 1]
[1, 1, 1]
[0, 2, 1]
[1, 2, 1]
[0, 3, 1]
[1, 3, 1]
[0, 0, 2]
[1, 0, 2]
[0, 1, 2]
[1, 1, 2]
[0, 2, 2]
[1, 2, 2]
[0, 3, 2]
[1, 3, 2]

This solution might be slower than alternatives so if speed is an issue you should probably improve it.

Upvotes: 2

Óscar López
Óscar López

Reputation: 235984

To obtain the exact sequence shown in the question (albeit in a different order, but that's not a problem) use this function:

import itertools as it

def combs(lst):
    return [list(e) for e in it.product(*(range(x+1) for x in lst))]

The result is as expected:

combs([1, 3, 2])

=> [[0, 0, 0], [0, 0, 1], [0, 0, 2], [0, 1, 0], [0, 1, 1], [0, 1, 2],
    [0, 2, 0], [0, 2, 1], [0, 2, 2], [0, 3, 0], [0, 3, 1], [0, 3, 2],
    [1, 0, 0], [1, 0, 1], [1, 0, 2], [1, 1, 0], [1, 1, 1], [1, 1, 2],
    [1, 2, 0], [1, 2, 1], [1, 2, 2], [1, 3, 0], [1, 3, 1], [1, 3, 2]]

Upvotes: 3

nneonneo
nneonneo

Reputation: 179392

Use itertools.product with a dynamically-specified list of iterators:

vals = [1,3,2]
for item in itertools.product(*[range(x+1) for x in vals]):
    print item

Output:

(0, 0, 0)
(0, 0, 1)
(0, 0, 2)
(0, 1, 0)
(0, 1, 1)
(0, 1, 2)
(0, 2, 0)
(0, 2, 1)
(0, 2, 2)
(0, 3, 0)
(0, 3, 1)
(0, 3, 2)
(1, 0, 0)
(1, 0, 1)
(1, 0, 2)
(1, 1, 0)
(1, 1, 1)
(1, 1, 2)
(1, 2, 0)
(1, 2, 1)
(1, 2, 2)
(1, 3, 0)
(1, 3, 1)
(1, 3, 2)

Upvotes: 5

Jblasco
Jblasco

Reputation: 3967

for ii in itertools.product(range(2),range(4),range(3):
    print ii
(0, 0, 0)
(0, 0, 1)
(0, 0, 2)
(0, 1, 0)
(0, 1, 1)
(0, 1, 2)
(0, 2, 0)
(0, 2, 1)
(0, 2, 2)
(0, 3, 0)
(0, 3, 1)
(0, 3, 2)
(1, 0, 0)
(1, 0, 1)
(1, 0, 2)
(1, 1, 0)
(1, 1, 1)
(1, 1, 2)
(1, 2, 0)
(1, 2, 1)
(1, 2, 2)
(1, 3, 0)
(1, 3, 1)
(1, 3, 2)

Upvotes: 2

Related Questions