迭代整数的Pythonic或最佳实践方法是什么?

时间:2013-01-30 18:21:42

标签: python casting type-conversion

在Python中迭代整数的最佳做法是什么?我发现我需要经常这样做,通常是详细的结果。例如,以下是我为Project Euler问题编写的两个函数:

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)它只是感觉完全不优雅。有没有其他方法来处理这个问题?我是否完全以错误的方式处理这些函数,即我是否应该迭代整数?

感谢您的帮助。

8 个答案:

答案 0 :(得分:3)

我个人认为for e in str(n)非常易读。

我发现不太引人注意的是重复调用str(n)内部循环(其中n是不变的。)

无论如何,我会以完全不同的方式实现这两个功能

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

答案 1 :(得分: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)

将这两个简单的情况与使用整数或长整数的实际数学进行比较:

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中进行。

答案 2 :(得分: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))

答案 3 :(得分:1)

如果您的号码不是“大规模” - 即停止播放,那么您可以将has_even_digit用作:

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

如果失败,优化将是1本身的按位 - 因为如果第一位被设置,二进制表示的任何东西都必须是奇数。虽然这与“整数”有关 - 而不是数字。

答案 4 :(得分:0)

对于偶数位数的迭代,您可以使用range's step参数:

range(start, end, step)

因此,在您的代码中,您可以这样做:

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

答案 5 :(得分:0)

您可以创建一个生成器:

def digits(num):
    while num > 0:
        yield num % 10
        num /= 10

答案 6 :(得分: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

答案 7 :(得分:0)

def has_even_digits(n):
    return bool(set('02468') & set(str(n)))