【问题标题】:What is the Pythonic or best practice way of iterating over an integer?迭代整数的 Pythonic 或最佳实践方法是什么?
【发布时间】:2013-01-14 16:22:29
【问题描述】:

在 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) 感觉完全不雅。有没有另一种方法来处理这个问题?我是否以完全错误的方式处理这些函数,即我是否不必遍历整数?

感谢您的帮助。

【问题讨论】:

  • 请注意:is_permutation_of('aab', 'abb') 将返回 True
  • @poke,感谢您的观察
  • 从下面的两个 cmets 看来,您似乎在问“我可以在不将 int 转换为 str 的情况下执行这些功能吗?”您可能可以,以类似 C 的方式,但为什么呢?将 int 转换为字符串是脚本语言中很棒的习惯用法和快捷方式之一。如果你认为它更快——它可能不是。而且肯定会有更多的代码。
  • 整数是不可迭代的,所以你所说的问题没有多大意义。阅读详细信息后,您实际上是在谈论迭代整数中的数字。在这种情况下,进行字符串转换是很自然的下一步。但是没有必要在你的 for 循环中一遍又一遍地这样做 - 只需在顶部添加一个 ndigits=str(n) 就足够了。
  • @thewolf,这正是我要问的。从各种答案来看,这听起来像是将整数转换为字符串是 Pythonic 迭代数字的方式。谢谢。

标签: python casting type-conversion


【解决方案1】:

我个人觉得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

【讨论】:

  • 我同意。通常最好有一个可读的解决方案而不是一个优雅的解决方案。
  • @NPE,我同意该行相当可读,但是一旦您执行以下操作就会变得混乱:for e in range(len(str(n)))
  • @ggundersen:但你为什么要这么做?你肯定会用enumerate()
  • 如果只需要遍历索引,为什么要使用enumerate(x)xrange(len(x)) 对我来说似乎更好。当然,str(n) 并不是首先获得以 10 为底的数字的可迭代数字的最佳方法。
  • @NPE,我对 Pyson 说了同样的话:我很欣赏这些优化,但我认为它错过了我更大的问题,即:我应该不只是迭代整数吗?我发布的函数只是我认为迭代有用的示例。
【解决方案2】:

如果您的数字不是“大量” - 即,让事情停止,那么您可以使用您的 has_even_digit 作为:

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

如果做不到这一点,优化将是使用1 本身按位进行 - 因为如果设置了第一位,则任何可以用二进制表示的东西都必须是奇数。虽然这与“整数”有关 - 而不是数字。

【讨论】:

    【解决方案3】:

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

    range(start, end, step)

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

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

    【讨论】:

      【解决方案4】:

      你可以创建一个生成器:

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

      【讨论】:

        【解决方案5】:

        我更喜欢我的变体而不是你的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 中完成。

        【讨论】:

        • 这些都很好@Pyson,但这些函数只是我迭代整数的例子;你是说真的不存在这样的情况还是只是在改进我的功能?不管怎样,谢谢。
        【解决方案6】:

        如果您将 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】:
          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))
          

          【讨论】:

            【解决方案8】:
            def has_even_digits(n):
                return bool(set('02468') & set(str(n)))
            

            【讨论】:

              猜你喜欢
              • 2015-09-11
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2012-05-30
              • 1970-01-01
              • 2016-05-05
              • 2022-01-01
              • 1970-01-01
              相关资源
              最近更新 更多