如何改进这种重度嵌套的for循环?

时间:2016-06-07 15:43:14

标签: python optimization

我有一个我想优化的功能,如果可能的话。但我不能轻易判断是否有更好的方法来重构(和优化)这个......

假设,

keys_in_order = ['A', 'B', 'C', 'D', 'E']
key_table = { 'A': {'A1': 'one', 'A2': 'two', 'A3': 'three', 'A4': 'four'},
'B': {'B1': 'one-one', 'B2': 'two-two', 'B3': 'three-three'},
... # mapping for 'C', 'D' here
'E': {'E1': 'one-one', 'E2': 'two-two', 'E3': 'three-three', 'E6': 'six-six'}
}

目的是将以上两个参数提供给函数,如下所示:

def generate_all_possible_key_combinations(keys_in_order, key_table):
    first_key = keys_in_order[0]
    second_key = keys_in_order[1]
    third_key = keys_in_order[2]
    fourth_key = keys_in_order[3]
    fifth_key = keys_in_order[4]

    table_out = [['Demo Group', first_key, second_key, third_key, fourth_key, fifth_key]] # just the header row so that we can write to a CSV file later

    for k1, v1 in key_table[first_key].items():
        for k2, v2 in key_table[second_key].items():
            for k3, v3 in key_table[third_key].items():
                for k4, v4 in key_table[fourth_key].items():
                    for k5, v5 in key_table[fifth_key].items():
                        demo_gp = k1 + k2 + k3 + k4 + k5
                        table_out.append([demo_gp, v1, v2, v3, v4, v5])

    return table_out

所以我们的目标是拥有一个包含所有可能的子键组合的表(即'A1B1C1D1E1','A1B1C1D1E2','A1B1C1D1E3'等)及其在key_table中的对应值

对我而言,目前通过dict key_table进行五次重度嵌套循环的代码是丑陋的,更不用说它在计算方面是低效的。有没有办法改善这个?我希望来自code_review的人们能够阐明我如何去做。谢谢!

2 个答案:

答案 0 :(得分:2)

我用另一种方法实现了。将key_table视为主词典。

我的逻辑是

  1. 从这里我将从主要词典中获得所有可能的子键。

    In [1]: [i.keys() for i in key_table.values()]
    Out[1]: 
    [['A1', 'A3', 'A2', 'A4'],
    ['C3', 'C2', 'C1'],
    ['B1', 'B2', 'B3'],
    ['E6', 'E1', 'E3', 'E2'],
    ['D2', 'D3', 'D1']]
    
  2. 然后我将这个列表列表作为单个列表。

    In [2]: print [item for sublist in [i.keys() for i in key_table.values()] for item in sublist]
    ['A1', 'A3', 'A2', 'A4', 'C3', 'C2', 'C1', 'B1', 'B2', 'B3', 'E6', 'E1', 'E3', 'E2', 'D2', 'D3', 'D1']
    
  3. 使用itertools.combinations实现了所有可能值的组合。它有5个元素,所以我给它作为硬编码方法。如果您有更多值,可以将其替换为len([i.keys() for i in key_table.values()])。这里提供了itertools.combinations的示例。那你就可以理解了。

    In [83]: for i in itertools.combinations(['A1','B1','C1'],2):
    ....:     print i
    ....:     
    ('A1', 'B1')
    ('A1', 'C1')
    ('B1', 'C1')
    
  4. 以下是一行实现的完整代码。

    for item in itertools.combinations([item for sublist in [i.keys() for i in key_table.values()] for item in sublist],5):
        print ''.join(item)
    

答案 1 :(得分:1)

一些优化:

  • 可以在嵌套循环
  • 之前计算各种key_table[?].items()
  • 您可以在demo_gp可用时计算demo_gp12 = k1 + k2的部分内容:demo_gp123 = demo_gp12 + k3v等。可以使用itertools数组来完成类似的事情。

正如@JohnColeman建议的那样,Date Time Qty 20160101 0800 4500 20160203 0900 6000 20160301 0810 3400 20160328 1710 5300 20160402 1201 6000 将是一个寻求简化它的好地方。