Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 替换嵌套的循环。。。还是不_Python_Loops_For Loop_Nested Loops - Fatal编程技术网

Python 替换嵌套的循环。。。还是不

Python 替换嵌套的循环。。。还是不,python,loops,for-loop,nested-loops,Python,Loops,For Loop,Nested Loops,我有一个脚本,它循环遍历一系列四个(或更少)字符的字符串。例如: aaaa aaab aaac aaad 如果您能够使用嵌套for循环实现它,如下所示: chars = string.digits + string.uppercase + string.lowercase for a in chars: print '%s' % a for b in chars: print '%s%s' % (a, b) for c in chars:

我有一个脚本,它循环遍历一系列四个(或更少)字符的字符串。例如:

aaaa
aaab
aaac
aaad
如果您能够使用嵌套for循环实现它,如下所示:

chars = string.digits + string.uppercase + string.lowercase

for a in chars:
    print '%s' % a   
    for b in chars:
        print '%s%s' % (a, b)
        for c in chars:
            print '%s%s%s' % (a, b, c)
            for d in chars:
                print '%s%s%s%s' % (a, b, c, d)

这种循环嵌套是一件坏事吗?如果是的话,有什么更好的方法来完成我正在做的事情呢?

有很多算法可以生成集合的每个排列。你想要的是一个相关的问题,但不是直接的分析

我不认为这是一件坏事,只要你理解(并记录:-)它。我不怀疑可能会有一种更为通灵的方式或聪明的解决方案(使用lambdas或诸如此类的东西),但我一直倾向于可读性而不是聪明性

由于您必须生成所有可能的1、2、3和4个字符的“单词”,因此此方法与任何方法一样好。我不确定需要多长时间,因为你能有效地(非常粗略地)产生1400万条生产线(但可能每个解决方案都会有这个问题)

预先计算常用前缀可能会提高速度,但最好通过测量来检查(始终检查,从不检查假设):


编辑:我实际上做了一些基准测试(使用WindowsPython2.6.1)-与原来的2.84相比,这个版本大约需要2.25个时间单位,因此速度快了26%。我认为这可能会保证它的使用(同样,只要它清楚地记录了它试图实现的目标)。

首先为程序员编写,其次为计算机编写。
如果理解起来清晰明了,那么它是正确的

如果速度很重要,而编译器无论如何都没有对其进行优化,如果您对其进行了测量,这就是问题所在,那么请考虑一种更快更聪明的方法

import string
import itertools

chars = string.digits + string.letters
MAX_CHARS = 4
for nletters in range(MAX_CHARS):
    for word in itertools.product(chars, repeat=nletters + 1):
        print (''.join(word))

这将打印您要查找的所有单词。如果需要更多/更少的单词,只需更改
MAX\u CHARS
变量即可。对于任何数量的字符,它仍然只有两个
for
s,您不必重复。而且可读性很强

我将以可读性最高、可扩展性最低的方式提交我的答案:)

编辑:实际上,这是不正确的,因为它将产生长度的所有字符串的副本,并且解决方案会产生不同的结果:

>>> list(map(''.join, itertools.chain.from_iterable(itertools.product("ab", 
...     repeat=r) for r in range(4)))) # @nosklo's 
[''‘a’、‘b’、‘aa’、‘ab’、‘ba’、‘bb’、‘aaa’、‘aab’、‘aba’、‘abb’、‘baa’, ‘bab’、‘bba’、‘bbb’]
它不能准确回答问题,但这将返回字母表中给定最大长度和字符的
n
th组合:

#!/usr/bin/python

def nth_combination(n, maxlen=4, alphabet='abc'):
    """
    >>> print ','.join(nth_combination(n, 1, 'abc') for n in range(3))
    a,b,c
    >>> print ','.join(nth_combination(n, 2, 'abc') for n in range(12))
    a,aa,ab,ac,b,ba,bb,bc,c,ca,cb,cc
    >>> import string ; alphabet = string.ascii_letters + string.digits
    >>> print ','.join(nth_combination(n, 4, alphabet) for n in range(16))
    a,aa,aaa,aaaa,aaab,aaac,aaad,aaae,aaaf,aaag,aaah,aaai,aaaj,aaak,aaal,aaam
    >>> print ','.join(nth_combination(n, 4, alphabet)
    ...                for n in range(0, 14000000, 10**6))
    a,emiL,iyro,mKz2,qWIF,u8Ri,zk0U,Dxav,HJi9,LVrM,P7Ap,UjJ1,YvSE,2H1h
    """
    if maxlen == 1:
        return alphabet[n]
    offset, next_n = divmod(n, 1 + len(alphabet)**(maxlen-1))
    if next_n == 0:
        return alphabet[offset]
    return alphabet[offset] + nth_combination(next_n-1, maxlen-1, alphabet)

if __name__ == '__main__':
    from doctest import testmod
    testmod()
当然,只有当您需要随机访问组合集,而不是总是遍历它们时,这才有意义


如果
maxlen
较高,则可以实现一些速度优化,例如,通过消除字符串串联,并在递归的每个级别重新计算
字母表
maxlen-1
的长度。非递归方法也可能有意义。

尝试想出一种比暴力更好的算法。也许是递归或者除法除法conquer@Perpetual,在我看来,既然你必须产生所有的可能性,那么无论它是不是蛮力都没有什么区别。当你可以最小化你需要的东西时,非暴力算法是好的,但我认为这里不是这样。递归使您的源代码更小,但仅此而已。语法错误。。。您缺少一个冒号。这应该提到它需要python 2.6,但除此之外,这就是我要发布的解决方案。:)“非常可读”?-我仍然认为原作更容易理解,但是我是一只恐龙,我从来没有见过itertools,所以我不会-1 you:-)。你能解释一下为什么当我看到两个明显嵌套的关键字副本时,它满足“no nested for”吗?实际上我想我应该做一次性能检查,看看itertools的速度有多快。结果令人惊讶——在Python2.6.1(Windows)下,itertools的速度要慢得多(2.16而不是0.45个time.clock()单位)。没有输出,在脚本中运行五次,以减少启动时间。不是每个程序员都是理论家。我们大多数人都有工作要在某个特定日期完成,并且不受cpu的约束。在这种情况下,mgb是正确的,您应该为程序员编写。OP的算法不是那样的,但这并不意味着mgb是错误的,也许没有帮助。我喜欢它。。。它就像一颗看不见的定时炸弹。它覆盖了所有的单词,注意“字符”列表中的空字符串。您的解决方案可读性更好,但它会产生不同的输出:是的,它会产生每个长度字符串的重复项。您可以通过始终执行简单的
a+b
而不是
“%s%s%”(a,b)
>>> list(map(''.join, itertools.chain.from_iterable(itertools.product("ab", 
...     repeat=r) for r in range(4)))) # @nosklo's 
['', 'a', 'b', 'aa', 'ab', 'ba', 'bb', 'aaa', 'aab', 'aba', 'abb', 'baa', 'bab', 'bba', 'bbb']
>>> ab = ['']+list("ab")
>>> list(map(''.join, (a+b+c for a in ab for b in ab for c in ab)))  
['', 'a', 'b', 'a', 'aa', 'ab', 'b', 'ba', 'bb', 'a', 'aa', 'ab', 'aa', 'aaa', 'aab', 'ab', 'aba', 'abb', 'b', 'ba', 'bb', 'ba', 'baa', 'bab', 'bb', 'bba', 'bbb']
>>> ab = "ab"
>>> list(map(''.join, itertools.chain([''], ab, (a+b for a in ab for b in ab),
...     (a+b+c for a in ab for b in ab for c in ab))))
['', 'a', 'b', 'aa', 'ab', 'ba', 'bb', 'aaa', 'aab', 'aba', 'abb', 'baa', 'bab', 'bba', 'bbb']
#!/usr/bin/python

def nth_combination(n, maxlen=4, alphabet='abc'):
    """
    >>> print ','.join(nth_combination(n, 1, 'abc') for n in range(3))
    a,b,c
    >>> print ','.join(nth_combination(n, 2, 'abc') for n in range(12))
    a,aa,ab,ac,b,ba,bb,bc,c,ca,cb,cc
    >>> import string ; alphabet = string.ascii_letters + string.digits
    >>> print ','.join(nth_combination(n, 4, alphabet) for n in range(16))
    a,aa,aaa,aaaa,aaab,aaac,aaad,aaae,aaaf,aaag,aaah,aaai,aaaj,aaak,aaal,aaam
    >>> print ','.join(nth_combination(n, 4, alphabet)
    ...                for n in range(0, 14000000, 10**6))
    a,emiL,iyro,mKz2,qWIF,u8Ri,zk0U,Dxav,HJi9,LVrM,P7Ap,UjJ1,YvSE,2H1h
    """
    if maxlen == 1:
        return alphabet[n]
    offset, next_n = divmod(n, 1 + len(alphabet)**(maxlen-1))
    if next_n == 0:
        return alphabet[offset]
    return alphabet[offset] + nth_combination(next_n-1, maxlen-1, alphabet)

if __name__ == '__main__':
    from doctest import testmod
    testmod()