【问题标题】:Best way to loop over a python string backwards向后循环python字符串的最佳方法
【发布时间】:2011-12-19 04:14:13
【问题描述】:

向后循环 python 字符串的最佳方法是什么?

对于所有需要 -1 偏移量,以下内容似乎有点尴尬:

string = "trick or treat"
for i in range(len(string)-1, 0-1, -1):
    print string[i]

以下看起来更简洁,但它是否真的生成了一个反向字符串,从而有轻微的性能损失?

string = "trick or treat"
for c in string[::-1]:
    print c

【问题讨论】:

  • 你写0-1作为范围的第二个参数有什么具体原因吗?当我尝试运行它时,它只适用于-1。我只是想知道这只是一个写作惯例还是我错过了什么。
  • @newbie 我猜是0 后来被固定为-1

标签: python string optimization iterator reverse


【解决方案1】:

字符串反转

def reverse(a_string):
    rev = ''
    for i in range(len(a_string)-1, -1, -1):
        rev = rev + a_string[i]
    return rev
print(reverse("This string should be reversed!"))

输出是: !desrever eb dluohs gnirts sihT

【讨论】:

  • 欢迎来到 StackOverflow!请注意,在 Python 中通常不鼓励在循环中写入 string = string + other,因为它会导致不必要的重复分配。几乎总是使用str.join 应该是首选,它只为新字符串分配一次内存。您还会注意到,您的 reverse 函数本质上是 reversed 内置函数的一个效率较低的版本,专门用于字符串。
  • 虽然这可以作为一个字符串反向函数,但正如 Brian 所说,这确实是 reversed 内置函数的一个更糟糕的版本,实际上并没有直接回答这个问题,即如何循环向后串。
【解决方案2】:

带有enumeratereversed 方法的Python 3:

string = "trick or treat"
for i, c in enumerate(reversed(string)):
    print(i, c)

您可以只使用 print(c) 来检索没有索引的每个字符。

【讨论】:

    【解决方案3】:

    这是一种在不使用 reversed 等内置功能的情况下反转字符串的方法。负步长值向后遍历。

    def reverse(text):
        rev = ''
        for i in range(len(text), 0, -1):
            rev += text[i-1]
        return rev
    

    【讨论】:

    • 请检查上述程序是否有效,否则会出现缩进错误
    • 我已更新答案以更正空格错误。这目前适用于 Python 2.7.7 shell。
    • -1:比切片差很多 (text[-1:-1:-1])。对于 100k 字符串,timeit 显示切片最差约 10 毫秒,函数平均 177 毫秒。
    • 好点。我并不是说要提供最优化的解决方案。我的解决方案很冗长,非常适合尝试学习一些基本任务背后的逻辑的初学者。您应该添加切片解决方案作为答案。
    • @Nathan 那么你的行为会促进与你所说的完全相反的目标:对于初学者来说,尤其立即学习做事的最佳方法至关重要。由于OP已经提到过,因此无需在切片上添加答案。
    【解决方案4】:

    在 Python 中使用 For 循环反转字符串

    outputStr = ''
    a = raw_input("Enter String: ")
    for i in range(len(a), 0, -1):
        outputStr += a[i-1]
    print outputStr
    

    【讨论】:

      【解决方案5】:
      def reverse(text):
          x = ""
          for i in range(len(text)):
              x = x + text[len(text)-i-1]
          return x
      

      【讨论】:

      • 欢迎来到 Stack Overflow!请解释您的代码的作用以及它为什么会解决问题。只包含代码的答案(即使它正在工作)通常不会帮助 OP 理解他们的问题。
      【解决方案6】:

      是的,第二个语法快捷方式创建了一个中间字符串,并具有相关的性能损失。

      第一个版本最好写成:

      for index, char in enumerate(reversed(s)):
         print "pos %d: %s" % (index, char)
      

      这很容易理解。 reversedenumerate` 都不需要复制字符串。

      还要小心使用string 作为变量名,因为它也是a module in the standard library 的名称。

      【讨论】:

      • 我不喜欢这个答案,因为使用 enumerate() 会使答案更难理解。这是双重事实,因为报告的索引是新位置,而不是原始位置。 +1 建议不要使用“字符串”作为变量名。
      • 我相信较短的问题会赢。有时我喜欢过度解释简单的答案。
      • 回滚到之前的版本。最后一个更改破坏了代码 - reversed 适用于序列,但不适用于枚举对象。
      【解决方案7】:

      在 Python 中,更少的代码通常更快。幸运的是,您不必猜测:

      python -mtimeit -s"s='x'*100000" "for x in s[::-1]: pass"
      100 loops, best of 3: 1.99 msec per loop
      
      python -mtimeit -s"s='x'*100000" "for x in reversed(s): pass"
      1000 loops, best of 3: 1.97 msec per loop
      
      python -mtimeit -s"s='x'*100000" "for i in xrange(len(s)-1, 0-1, -1): s[i]"
      100 loops, best of 3: 4.95 msec per loop
      

      因此,较短的代码会更快一些,但会带来内存开销。

      【讨论】:

      • 在进行这样的计时时注意本地化 range() 和 len();否则,一次性全局查找往往会支配时间(尤其是当只运行 100 个循环时)。
      • @Raymond Hettinger:显然迭代 100000 个字符将主导 2 个全局查找。
      【解决方案8】:
       string = "trick or treat"
       for c in string[::-1]:
           print c
      

      我会用那个。尽管可能有更好的方法(但我对此表示怀疑),但它可能相当快。

      编辑: 实际上,使用我一起破解的程序进行第二次测试,reversed 可能是要走的路。

       ==== Results ====
      Sample 1: 0.0225071907043 # Using a for loop
      Sample 2: 0.0100858211517 # Using reversed
      

      【讨论】:

        【解决方案9】:
        string = "trick or treat"
        for c in reversed(string):
            print c
        

        会做我认为你想做的事。它使用迭代器。这应该适用于任何实现了 __reveresed__() 或 __len__() 和 __getitem__() 的东西。 __getitem__() 必须接受从 0 开始的 int 参数。

        【讨论】:

          【解决方案10】:

          reversed 接受一个可迭代对象并返回一个向后移动的迭代器。 string[::-1] 很好,但它会创建一个新的反转字符串。如果你只是想迭代,那么这可能会更好:

          for c in reversed(string):
              print c
          

          如果你以后想使用反转的字符串,创建一次会更好。

          【讨论】:

            【解决方案11】:

            试试 reversed 内置:

            for c in reversed(string):
                 print c
            

            reversed() 调用将创建一个迭代器,而不是复制整个字符串。

            PEP 322 详细介绍了 reversed() 的动机及其相对于其他方法的优势。

            【讨论】:

            • reversed 不支持缓冲协议,因此不适用于re
            • 进一步调查显示re 直接与内存缓冲区一起工作。因此,如果不复制数据,就不可能为它反转一个字符串。
            猜你喜欢
            • 2023-03-11
            • 1970-01-01
            • 2013-01-11
            • 1970-01-01
            • 2012-03-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多