7

一連の4つ(またはそれ以下)の文字列をループするスクリプトがあります。例えば:

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)

この種のループは悪いことをネストしていますか?もしそうなら、私がしていることを達成するためのより良い方法は何でしょうか?

4

7 に答える 7

16
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))

15018570これにより、探しているすべての単語が出力されます。単語を増やしたり減らしたりしたい場合は、MAX_CHARS変数を変更してください。任意の数の文字に対して2 つforの s しかないため、同じことを繰り返す必要はありません。そしてかなり読みやすいです。.

于 2009-01-27T02:46:03.343 に答える
6

最も読みやすく、最もスケーラブルではない回答として提出します:)

import string
chars = [''] + list(string.lowercase)

strings = (a+b+c+d for a in chars
                   for b in chars
                   for c in chars
                   for d in chars)

for string in strings:
    print string

編集:実際には、長さ <4 のすべての文字列の複製が生成されるため、これは正しくありません。配列から空の文字列を削除するcharsと、4 文字の文字列が生成されます。

通常、私はこの回答を削除しますが、同じ長さの文字列を生成する必要がある場合は、まだ好きです。

于 2009-01-27T03:07:09.103 に答える
4

最初にプログラマーのために、次にコンピューターのために書いてください。
理解することが明確で明白である場合、それは正しいです。

速度が重要で、コンパイラがとにかくそれを最適化しない場合、そしてそれを測定し、それが問題である場合、より高速で賢い方法を考えてください!

于 2009-01-27T02:37:32.360 に答える
3

あなたがそれを理解(そして文書化:-)すれば、それは悪いことではないと思います。よりPython的な方法や賢い解決策(ラムダなどを使用)があるかもしれないことは間違いありませんが、私は常に賢さよりも読みやすさを優先してきました。

1文字、2文字、3文字、および4文字の「単語」のすべての可能性を生成する必要があるため、この方法は他の方法と同じように優れています。(非常に大まかに)1400万行の出力を効果的に生成しているので、どれくらいの時間がかかるかわかりません(ただし、おそらくすべてのソリューションにその問題があります)。

共通のプレフィックスを事前に計算すると速度が向上する場合がありますが、それを測定してチェックすることをお勧めします(常にチェックし、想定しないでください)。

chars = string.digits + string.uppercase + string.lowercase
for a in chars:
    print a
    for b in chars:
        ab = '%s%s' % (a, b)
        print ab
        for c in chars:
            abc = '%s%s' % (ab, c)
            print abc
            for d in chars:
                print '%s%s' % (abc, d)

編集:私は実際にいくつかのベンチマークを実行しました(Windows-Python 2.6.1を使用)-このバージョンは、元の2.84と比較して約2.25時間単位かかるため、26%高速です。私はそれがその使用を正当化するかもしれないと思います(それが何を達成しようとしているのかが明確に文書化されている限り)。

于 2009-01-27T02:35:03.833 に答える
2

@noskloと@Triptychソリューションでは、異なる結果が生成されます。

>>> 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',
 「バブ」、「ババ」、「ブッブ」]
>>> 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」]

@nosklo のものと同じ出力を生成する、修正された @Triptych のソリューションを次に示します。

>>> 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',
 「バブ」、「ババ」、「ブッブ」]
于 2009-01-27T11:01:47.320 に答える
1

セットのすべての順列を生成するための多くのアルゴリズムがあります。ここで必要なのは関連する問題ですが、直接類似しているわけではありません。 推奨読書

于 2009-01-27T02:34:44.957 に答える
1

質問に正確に答えるわけではありませんが、これは、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の長さを再計算するなど、速度の最適化を達成できます。非再帰的なアプローチも理にかなっています。alphabetmaxlen-1

于 2009-01-27T12:15:51.990 に答える