【问题标题】:Reducing nested for loops that build dictionaries/strings (Branching tree style)减少构建字典/字符串的嵌套 for 循环(分支树样式)
【发布时间】:2014-09-18 15:53:57
【问题描述】:

对于最近的脚本,我必须通过分支树迭代可能的流。我构建了一个字典,其中包含每个项目的运行状态,以便我进行评估。例如:

for a in range(0, 2):
  for b in range(0, 2):
    for c in range(0, 2):
      for d in range(0, 2):
        ...
        run = [a,b,c,d ...]

不幸的是,它开始时规模很小,但后来发展到十几个州。如何减少这种情况以消除所有嵌套循环?

如果某些州有 3 个或 4 个州而不是 2 个州,类似的答案会有所不同吗?

同样,如果每个循环都来自函数列表,同样的问题会受到怎样的影响?我怀疑它会是一样的。例如:

def leet_lookup(char):
    table = {"a": ["a","A","@"],
            "b": ["b", "B", "8"],
            "c": ["c", "C", "<"],
            "e": ["e", "E", "3"],
            "i": ["i", "I", "1"],
            "l": ["l", "L", "1"],
            "o": ["o", "O", "0"],
            "t": ["t", "T", "7"] }
    try:
        result = table[char.lower()]
    except KeyError:
        result = [char.lower(), char.upper()]
    return result

result = []
# V o l l e y b a l l = 10 chars
for c1 in leet_lookup('v'):
  for c2 in leet_lookup('o'):
    for c3 in leet_lookup('l'):
      for c4 in leet_lookup('l'):
        for c5 in leet_lookup('e'):
          for c6 in leet_lookup('y'):
            for c7 in leet_lookup('b'):
              for c8 in leet_lookup('a'):
                for c9 in leet_lookup('l'):
                  for c10 in leet_lookup('l'):
                    result.append("%s%s%s%s%s%s%s%s%s%s" % (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10))

【问题讨论】:

    标签: python for-loop nested-loops


    【解决方案1】:

    再次向itertools寻求解决方案是一个问题。

    对于第一个问题,只需使用product

    from itertools import product
    for run in product(range(2), repeat=5):
        print(run)
    
    # (0, 0, 0, 0, 0)
    # (0, 0, 0, 0, 1)
    # (0, 0, 0, 1, 0)
    # etc.
    

    如果每个指标有更多的状态,要么 a) 每个指标有相同数量的状态,你可以简单地改变 range 的参数,或者 b) 不同的指标有不同数量的状态,在这种情况下你可以执行类似于以下答案的操作,将 leet_lookup 调用替换为 range 并使用状态编号列表而不是 lookups

    对于第二个,您可能想要构建一个可迭代列表,然后您可以在其上使用product

    lookups = ['v', 'o', 'l', 'l']
    items = [leet_lookup(a) for a in lookups]
    for c in product(*items):
        print(c)
    
    # ('v', 'o', 'l', 'l')
    # ('v', 'o', 'l', 'L')
    # ('v', 'o', 'l', '1')
    # ('v', 'o', 'L', 'l')
    # etc.
    

    一般来说,如果您遇到任何涉及迭代器组合或转换的问题,您应该首先查找itertools 函数或recipe

    【讨论】:

    • 优秀的答案和建议,第二个特别令人生畏,但您的解决方案非常棒!谢谢
    【解决方案2】:

    您希望所有 table 字典值之间的所有排列,因此您可以使用 itertools 模块进行查找,这是更多的 pythonicmapjoin 函数来连接它们!

    import itertools
    table = {"a": ["a","A","@"],
            "b": ["b", "B", "8"],
            "c": ["c", "C", "<"],
            "e": ["e", "E", "3"],
            "i": ["i", "I", "1"],
            "l": ["l", "L", "1"],
            "o": ["o", "O", "0"],
            "t": ["t", "T", "7"] }
    
    for pro in itertools.product(table['a'],table['b'],table['c'],table['e'],table['i'],table['l'],table['o'],table['t']):
         print ''.join(pro)
    

    一些输出:

    @8<3Il0T
    @8<3Il07
    @8<3ILot
    @8<3ILoT
    @8<3ILo7
    @8<3ILOt
    @8<3ILOT
    @8<3ILO7
    @8<3IL0t
    ...
    

    【讨论】:

    • 感谢您的解决方案。但是,这似乎只对表中的每个字符进行排列,并且不能根据需要对提供的字符串起作用。
    猜你喜欢
    • 2020-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-25
    • 2019-03-29
    • 2022-01-03
    • 2019-09-30
    • 1970-01-01
    相关资源
    最近更新 更多