简体   繁体   English

有没有一种方法可以有效地迭代Python中的“嵌套”组合?

[英]Is there a way to efficiently iterate over 'nested' combinations in Python?

I am unsure how to define the problem I wish to solve, but from a combinations of numbers, eg: 我不确定如何定义我要解决的问题,但是要结合数字,例如:

(4, 3, 2) (4、3、2)

I wish to make an iterator that goes over all 'nested' combinations of these numbers. 我希望做一个遍历这些数字所有“嵌套”组合的迭代器。 What I mean by this is that it iterates over: 我的意思是迭代:

(0, 0, 0), (0, 1, 0), (0, 2, 0), (0, 3, 0), (0, 1, 1), (0, 1, 2), (0, 2, 1), (0, 2, 2), ... (0,0,0),(0,1,0),(0,2,0),(0,3,0),(0,1,1),(0,1,2),(0 ,2、1),(0、2、2),...

(1, 0, 0), (1, 1, 0), (1, 2, 0), (1, 3, 0), (1, 1, 1), (1, 1, 2), (1, 2, 1), (1, 2, 2), ... (1、0、0),(1、1、0),(1、2、0),(1、3、0),(1、1、1),(1、1、2),(1 ,2、1),(1、2、2),...

... ...

(4, 0, 0), (4, 1, 0), (4, 2, 0), (4, 3, 0), (4, 1, 1), (4, 1, 2), (4, 2, 1), (4, 2, 2), ... (4,0,0),(4,1,0),(4,2,0),(4,3,0),(4,1,1),(4,1,2),(4 ,2、1),(4、2、2),...

Preferably it could also be constrained by a maximum sum capacity during the generation of combinations (ie sum(combination) < capacity). 优选地,它也可以在组合的产生期间受到最大总容量的约束(即,总和(组合)<容量)。

I have created a recursive algorithm that generates these combinations, but it is very slow and hope there is a more efficient method. 我创建了一个生成这些组合的递归算法,但是它很慢,希望有一种更有效的方法。

import numpy as np 

def combinations(current, c, c_set):
    c_rec = c.copy()
    if(current == 0):
        while(c_rec[current] + 1 <= numbers[current] and c_rec[current] + 1 < capacity):
            c_rec[current] += 1
            c_set.append(c_rec.copy())

    while(c_rec[current] + 1 <= numbers[current] and c_rec[current] + 1 < capacity):
        c_rec[current] += 1
        combinations(current - 1, c_rec, c_set)
        c_set.append(c_rec)

numbers = (4,3,2)
n = len(numbers)
capacity = 7
c_init = np.zeros(n)
c_set = [c_init]            
combinations(n - 1, c_init, c_set)

You can make use of itertools.product for this 您可以为此使用itertools.product

from itertools import product

li = [4, 3, 2]

#Create a list of ranges
res = [range(item+1) for item in li]
#[range(0, 5), range(0, 4), range(0, 3)]

#Calculate cartesian product between elements of each list
prod = product(*res)

#Iterate over the elements
for item in prod:
    print(item)

The output will be 输出将是

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

I might not have fully understood your question, but wouldn't a simple nested for-loop structure solve your problem? 我可能还没有完全理解您的问题,但是简单的嵌套for循环结构不会解决您的问题吗?

for x in range(4):
    for y in range(3):
        for z in range(2):
            print((x, y, z))

You can use recursion with a generator: 您可以将递归与生成器一起使用:

start = (4, 3, 2)
def groups(d):
  yield d
  for i, [a, b] in enumerate(zip(d, start)):
    if a < b:
      yield from groups(tuple([*d[:i], d[i]+1, *d[i+1:]]))

result = set(groups((0, 0, 0)))

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), (2, 0, 0), (2, 0, 1), (2, 0, 2), (2, 1, 0), (2, 1, 1), (2, 1, 2), (2, 2, 0), (2, 2, 1), (2, 2, 2), (2, 3, 0), (2, 3, 1), (2, 3, 2), (3, 0, 0), (3, 0, 1), (3, 0, 2), (3, 1, 0), (3, 1, 1), (3, 1, 2), (3, 2, 0), (3, 2, 1), (3, 2, 2), (3, 3, 0), (3, 3, 1), (3, 3, 2), (4, 0, 0), (4, 0, 1), (4, 0, 2), (4, 1, 0), (4, 1, 1), (4, 1, 2), (4, 2, 0), (4, 2, 1), (4, 2, 2), (4, 3, 0), (4, 3, 1), (4, 3, 2)]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM