4

Pythonで整数を反復処理するためのベストプラクティスは何ですか?私は頻繁にそうする必要があることに気づきました。通常、詳細な結果が得られます。たとえば、プロジェクトオイラーの問題のために私が書いた2つの関数は次のとおりです。

def is_permutation_of(n, m):
    """ Return True if n is a permutation of m, else False
    """
    if len(str(n)) != len(str(m)):
        return False
    for d in str(n):
        if d not in str(m):
            return False
    return True

そして別の:

def has_even_digit(n):
    """ Return True if n has an even digit, else False
    """
    evens = ['0', '2', '4', '6', '8']
    for e in evens:
        if e in str(n):
            return True
    return False

冗長性に加えて、1)各型変換に関連する計算コストが必要であり、2)完全にエレガントでないと感じます。この問題に対処する別の方法はありますか?私はこれらの関数を完全に間違った方法で実行していますか?つまり、整数を反復処理する必要はありませんか?

助けてくれてありがとう。

4

8 に答える 8

3

個人的にはfor e in str(n)とても読みやすいです。

見た目があまり良くないのは、str(n)内側のループへの繰り返しの呼び出しです ( wherenは不変です)。

とにかく、両方の機能をまったく異なる方法で実装します

def is_permutation_of(n, m):
   return sorted(str(n)) == sorted(str(m))

def has_even_digit(n):
   if n == 0:
      return True
   while n != 0:
      if n % 2 == 0:
         return True
      n //= 10
   return False
于 2013-01-30T18:24:55.787 に答える
3

私はあなたの代わりに私のバリアントを好むis_permutation_of:

def is_perm(a,b): return sorted(str(a)) == sorted(str(b))

そして、私はこれがより良いと思いますhas_even_digit

def has_even_digit(n):
    evens=set(['0', '2', '4', '6', '8'])
    return any(c in evens for c in str(n))

または、セットではなくタプルを使用することもできます:

def has_even_digit(n):
    return any(c in ('0', '2', '4', '6', '8') for c in str(n))

編集

コメント スレッドから、次のようなものを探していると思います。

# pseudo code -- don't use -- not syntactically correct
for d in 123456:      # integer
   # do something with each digit...

Python では整数は反復をサポートしていないため、これは機能しません。さらに、文字列で行うのは非常に慣用的で簡単であるため、整数の反復のようなものは実際には必要ありません。

これは、文字列でそれを行うが、単一の整数桁を生成する Python フレームワークです。

for d in [int(c) for c in str(123456)]:
    # d is a left (most significant) to right integer digit - do what you want with it...

右から左に同​​じ番号が必要な場合:

for d in [int(c) for c in str(123456)[::-1]]:
    # Now right (least significant digit) to left (most significant digit)

これら 2 つの単純なケースと、整数または long を使用した実際の計算を比較してください。

def int_iter(n,reverse=False):
    rtr=[]
    if not isinstance(n, (int,long)):
        raise ValueError('n must be int or long')

    while n:
        rtr.append(n%10)
        n/=10

    if reverse:
        return rtr[::-1]    
    else:
        return rtr  

文字列を使用する方がはるかに簡単で、おそらく高速です。超高速が必要な場合は、C で実行してください。

于 2013-01-30T18:28:05.010 に答える
2
def is_permutation_of(n, m):
    return sorted(n) == sorted(m)

evens=re.compile('[02468]')
def has_even_digit(n):
    return evens.search(str(n))
于 2013-01-30T18:31:26.970 に答える
1

数値が「大規模」でない場合、つまり物事を停止させる場合は、次のように使用できますhas_even_digit

>>> a = 123456789
>>> any(i % 2 == 0 for i in map(int, str(a)))
True

それができない場合、最適化は1それ自体でビットごとになります。最初のビットが設定されている場合、バイナリで表現できるものはすべて奇数でなければならないためです。それは「整数」に関連していますが、数字ではありません。

于 2013-01-30T18:25:26.957 に答える
0
def has_even_digits(n):
    return bool(set('02468') & set(str(n)))
于 2013-01-30T18:37:39.867 に答える
0

偶数桁を反復するには、範囲のstepパラメーターを使用できます。

range(start, end, step)

したがって、コードで次のことができます。

for e in range(0, 8, 2):

于 2013-01-30T18:26:59.833 に答える
0

ジェネレーターを作成できます:

def digits(num):
    while num > 0:
        yield num % 10
        num /= 10
于 2013-01-30T18:27:04.033 に答える
0

is_permutation_of の計算コストは​​、それらを別の変数に格納するだけで簡単に軽減されます。

def is_permutation_of(n, m):
    """ Return True if n is a permutation of m, else False
    """
    sn = str(n)
    sm = str(m)
    if len(sn) != len(sm):
        return False
    for d in sn:
        if d not in sm:
            return False
    return True
于 2013-01-30T18:29:59.203 に答える