繁体   English   中英

在python中使用递归来组合可变大小的列表

[英]Use recursion in python to combine lists of variable sizes

我有一个问题,随着问题的发展,这有点麻烦。

情况:

我需要将大小可变的列表中的项目与大小可变的元素进行组合,存储这些组合,然后对其进行遍历。 我尝试过itertools,但是得到的组合太多,我不知道如何正确地进行“清洁”。 通过创建与输入列表中“ op”元素数量一样多的for循环,可以得到正确的组合。

示例:注意:“ op”词典的数量可能有所不同! 忽略这样的值,重要的是,我使用“ op”字典的列表来基本上获取Nuke GUI元素(称为NoOp节点)中的所有自定义控件。 我需要遍历每个值的每个控件,并进行所有可能的组合:

for option1 in op1["options"]:
    for option2 in op2["options"]:
        for option3 in op3["options"]:
            print op1["control"], option1, op2["control"], option2,   op3["control"], option3     

现在,我只是想让我了解如何定义基本情况:/

def getCombos(controls, n = 0):
        #combos = []
        if n == 0:
            #return [(control["control"], option) for control in controls for option in control["options"]]
            return [(item["control"], option) for item in controls for option in item["options"]]
        else:
            for control in controls:
                return(getCombos(controls, n-1))
                n -= 1


op1 = {"control": "Material", "options": ["Glass", "Metal", "Wood"]}
op2 = {"control": "Base",
       "options": ["Chrome", "Brass", "Bronce", "Gold", "Nickel", "Red Gold"]}
op3 = {"control": "Color", "options": ["Red", "Blue", "Green", "Cyan", "SomeWonderfulNewColor"]}


controls = [op1, op2, op3]
#NOTE: number of elements (dict) in list controls may vary!

for i,combo in enumerate(getCombos(controls, n=len(controls))):
    print i, combo

在ATM上,此脚本仅以递归方式打印控件

我如何在这种情况下使用递归,更重要的是,我应该完全使用递归吗?如果是,如何处理这种情况并将其分解为各个组成部分? 干杯,

不能100%确定要实现的目标,但是如果要获得所有选项的组合,则应使用itertools.product

>>> list(itertools.product(op1["options"], op2["options"], op3["options"]))
[('Glass', 'Chrome', 'Red'),
 ('Glass', 'Chrome', 'Blue'),
 ('Glass', 'Chrome', 'Green'),
 ...
 ('Wood', 'Red Gold', 'Cyan'),
 ('Wood', 'Red Gold', 'SomeWonderfulNewColor')]

如果要将它们与各自的control结合使用,则可以编写一个辅助函数来获取对,然后获得这些对的product

>>> pairs = lambda op: [(op["control"], o) for o in op["options"]]
>>> pairs(op1)
[('Material', 'Glass'), ('Material', 'Metal'), ('Material', 'Wood')]

>>> list(itertools.product(*map(pairs, (op1, op2, op3))))
[(('Material', 'Glass'), ('Base', 'Chrome'), ('Color', 'Red')),
 (('Material', 'Glass'), ('Base', 'Chrome'), ('Color', 'Blue')),
 (('Material', 'Glass'), ('Base', 'Chrome'), ('Color', 'Green')),
 ...
 (('Material', 'Wood'), ('Base', 'Red Gold'), ('Color', 'Cyan')),
 (('Material', 'Wood'), ('Base', 'Red Gold'), ('Color', 'SomeWonderfulNewColor'))]

绝对应该使用递归:

def print_all(controls, idx, combination):
    if idx == len(controls):
        print(combination)
        return

    for x in controls[idx]['options']:
        print_all(controls, idx+1, combination + " " + controls[idx]['control'] + " " + str(x))


op1 = {"control": "Material", "options": ["Glass", "Metal", "Wood"]}
op2 = {"control": "Base",
   "options": ["Chrome", "Brass", "Bronce", "Gold", "Nickel", "Red Gold"]}
op3 = {"control": "Color", "options": ["Red", "Blue", "Green", "Cyan", "SomeWonderfulNewColor"]}
op4 = {"control": "year", "options": [2010, 2020]}

controls = [op1, op2, op3, op4]

print_all(controls, 0, "")

这是一种通过三个步骤打印所有组合的方法:

  1. {control: control_val, options: options_vals}转到{control_val: options_vals} 这是通过from_record函数完成的。
  2. {control_val: options_vals}转换为[(control_val, options_val)] 这是通过iter_dict完成的。
  3. 在所有不同的操作中获取此类列表的产品。
  4. 格式化和打印。 3和4由print_combinations处理。

from itertools import product


def from_record(dct):
    return {dct["control"]: dct["options"]}


def iter_dict(dct):
    yield from ((k, v) for k, vs in dct.items() for v in vs)


def print_combinations(dcts):
    for item in product(*(iter_dict(from_record(dct)) for dct in dcts)):
        print(", ".join(["{}: {}".format(*t) for t in item]))


op1 = {"control": "Material", "options": ["Glass", "Metal", "Wood"]}
op2 = {
    "control": "Base",
    "options": ["Chrome", "Brass", "Bronce", "Gold", "Nickel", "Red Gold"],
}
op3 = {
    "control": "Color",
    "options": ["Red", "Blue", "Green", "Cyan", "SomeWonderfulNewColor"],
}

print_combinations([op1, op2, op3])

# e.g.
# Material: Glass, Base: Chrome, Color: Red
# Material: Glass, Base: Chrome, Color: Blue
# Material: Glass, Base: Chrome, Color: Green
# Material: Glass, Base: Chrome, Color: Cyan
# Material: Glass, Base: Chrome, Color: SomeWonderfulNewColor

另外,通过组合不同的选项,可以更紧凑地列出所有可能的组合:

res = dict()
ops = [op1, op2, op3]
for op in ops:
    res.update(from_record(op))


# {'Base': ['Chrome', 'Brass', 'Bronce', 'Gold', 'Nickel', 'Red Gold'],
 # 'Color': ['Red', 'Blue', 'Green', 'Cyan', 'SomeWonderfulNewColor'],
 # 'Material': ['Glass', 'Metal', 'Wood']}

暂无
暂无

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

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