2017-02-21 15 views
5

Ok. Я ищу самый умный и более компактный способ сделать эту функциюPython: Генерирование всех массивов n-длины комбинаций значений в диапазоне

def f(): 
    [[a,b,c] for a in range(6) for b in range(6) for c in range(6)] 

, которые должны генерировать все комбинации для значений а, b, c нравится:

[0,0,0] 
[0,0,1] 
[0,0,2] 
... 
[1,0,0] 
[1,0,1] 
... 

и так далее. ..

Но я хочу, чтобы это было гибким, поэтому я могу изменить диапазон или итерабельность, а также длину сгенерированных массивов. Диапазон легкая вещь:

def f(min, max): 
    [[a,b,c] for a in range(min,max) for b in range(min,max) for c in range(min,max)] 

Это нормально для 3 длины массивов, но я думаю, теперь делают массивы 4 длины или 7 длиной массивы и генерировать все комбинации для них в том же диапазоне.

Он должен существовать простым способом, возможно, с конкатенацией массивов или списками понимания гнездования в некотором роде, но мои решения кажутся слишком сложными.

Извините за такой длинный пост.

+2

Параметр 'itertools' модуль имеет' функцию product', которая делает именно то, что вы «Ищем. 'из продукта импорта itertools; продукт (диапазон (6), диапазон (6), диапазон (6)) '. Какой бы итератор не помещал последние циклы быстрее. – Elliot

ответ

3

Вы можете использовать itertools.product, который является удобной функцией для вложенных итераций. Она также имеет repeat -argument, если вы хотите повторить те же iterable несколько раз:

>>> from itertools import product 

>>> amin = 0 
>>> amax = 2 
>>> list(product(range(amin, amax), repeat=3)) 
[(0, 0, 0), (0, 0, 1), (0, 1, 0), (0, 1, 1), (1, 0, 0), (1, 0, 1), (1, 1, 0), (1, 1, 1)] 

Чтобы получить list из list можно использовать map:

>>> list(map(list, product(range(amin, amax), repeat=3))) 
[[0, 0, 0], [0, 0, 1], [0, 1, 0], [0, 1, 1], [1, 0, 0], [1, 0, 1], [1, 1, 0], [1, 1, 1]] 

Однако product итератор так что действительно эффективный, если вы просто перебираете его, а не бросаете его на list. По крайней мере, если это возможно в вашей программе. Например:

>>> for prod in product(range(amin, amax), repeat=3): 
...  print(prod) # one example 
(0, 0, 0) 
(0, 0, 1) 
(0, 1, 0) 
(0, 1, 1) 
(1, 0, 0) 
(1, 0, 1) 
(1, 1, 0) 
(1, 1, 1) 
+0

Наконец-то я сделал один слой с '[list (elem) для элемента в продукте (* repeat (iterable, times))]' – madtyn

1

itertools имеет все необходимое. combination_with_replacement будет генерировать комбинации заданной длины с повторяющимися элементами из заданного итерабельного. Обратите внимание, что возвращаемое значение будет итератором.

def f(min, max, num):  
    return itertools.combinations_with_replacement(range(min, max), num) 
+0

Приятно для других ситуаций, но мне нужно [0,0,1]! = [1,0,0]. Приказ имеет значение. Может быть, мне следовало бы объяснить лучше. Я напишу это, хотя – madtyn

+0

Правильно, тогда, как утверждают некоторые другие ответы - itertools.product будет лучше. – Pearley

6

Вы можете использовать itertools.product:

from itertools import product 

def f(mn, mx, n): 
    return list(product(*[range(mn, mx)]*n))) 

падение list, чтобы вернуть генератор для повышения эффективности памяти.

-1

То, что вы ищете, является декартовым продуктом диапазонов.К счастью, это уже существует в itertools

import itertools 
print(list(itertools.product(range(0,5), range(0,5), range(0,5)))) 
1

Чистая реализация питон:

k=2 # k-uples 
xmin=2 
xmax=5 
n=xmax-xmin 

l1 = [x for x in range(n**k)] 
l2 = [[ x//n**(k-j-1)%n for x in l1] for j in range(k)]   
l3 = [[ xmin + l2[i][j] for i in range(k)] for j in range(n**k)] 

l3 является:

[[2 2] 
[2 3] 
[2 4] 
[3 2] 
[3 3] 
[3 4] 
[4 2] 
[4 3] 
[4 4]] 
+0

Вы должны просмотреть код. * // дает синтаксическую ошибку – madtyn

+0

Это '//'. Он работает нормально – madtyn

+0

Следует называть его «чистой встроенной» реализацией. Я считаю, что это не-pythonic из-за нечитаемости и, возможно, большего объема памяти и времени накладных расходов, чем при использовании функций из стандартной библиотеки Python. – Pearley