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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在python中使用递归来组合可变大小的列表相关的知识,希望对你有一定的参考价值。

我有一个问题的问题,随着问题的出现会产生一些问题。

情况:

我需要将可变大小的列表中的项目与可变大小的元素组合在一起,存储这些组合,然后迭代它们。我尝试过itertools,但是我得到了太多的组合,我不知道如何正确地“清理”。我通过创建与输入列表中“op”元素的数量一样多的for循环来获得正确的组合。

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

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']}

以上是关于在python中使用递归来组合可变大小的列表的主要内容,如果未能解决你的问题,请参考以下文章

使用递归从 char 列表中打印 n 长度组合

递归与回溯:python列表组合问题

初识Python

python中不可变的组合数据类型

查找列表中的最小元素(递归) - Python

从递归函数的基本情况返回语句(Python)