【问题标题】:Splitting a string into 2-letter segments [duplicate]将字符串拆分为 2 个字母的段 [重复]
【发布时间】:2012-09-11 13:47:27
【问题描述】:

我有一个字符串,我需要将它分成 2 个字母的部分。例如,'ABCDXY' 应变为 ['AB', 'CD', 'XY']。奇数字符情况下的行为可能完全是任意的(我会提前检查长度)。

有没有什么办法可以避免丑陋的循环?

【问题讨论】:

标签: python string python-3.x iterator


【解决方案1】:
>>> [s[i:i + 2] for i in range(0, len(s), 2)]
['AB', 'CD', 'XY']

【讨论】:

  • 这是一个循环。 OP 说“没有循环”
  • 他确实说过“没有丑陋的循环”......这当然可以避免这种情况。 :-)
  • 也许这是唯一的方法。我想有时需要循环。
  • 好吧,我以“不是循环的标准”的方式理解它,我认为列表推导会很好。让我们看看 OP 怎么说... :-)
  • 列表推导几乎不是一个循环,所以这符合条件:)
【解决方案2】:

使用正则表达式!

>>> import re
>>> s = "ABCDXYv"
>>> re.findall(r'.{1,2}',s,re.DOTALL)
['AB', 'CD', 'XY', 'v']

我知道这已经有一段时间了,但我又回到了这个问题上,很好奇哪种方法更好;我的:r'.{1,2}' 或乔恩的r'..?'。从表面上看,Jon 看起来好多了,我认为它会比我的快得多,但我惊讶地发现不是这样,所以我想我会分享:

>>> import timeit
>>> timeit.Timer("re.findall(r'.{1,2}', 'ABCDXYv')", setup='import re').repeat()
[1.9064299485802252, 1.8369554649334674, 1.8548105833383772]
>>> timeit.Timer("re.findall(r'..?', 'ABCDXYv')", setup='import re').repeat()
[1.9142223469651611, 1.8670038395145383, 1.85781945659771]

这表明r'.{1,2}' 确实是更好/更快的选择。 (但只是轻微)

【讨论】:

  • 小心,如果字符串包含换行符,这将无法正常工作。
  • @TimPietzcker 你是对的,我会加上标志来处理这种情况。
  • () 在正则表达式中是不必要的:re.findall('(?s)..', s)
  • or take the last character in the string and add that to your list at the end. -- def grouper() 似乎有点复杂——正则表达式可以是.{1,2}
  • 您可以使用..? 作为正则表达式。
【解决方案3】:

你可以试试:

s = 'ABCDEFG'
r = [s[i:i+2] for i in xrange(0, len(s), 2)]

# r is ['AB', 'CD', 'EF', 'G']

更新 2

如果您不关心奇数字符,您可以使用正则表达式(避免循环):

s = 'ABCDEFG'
r = re.compile('(..)').findall(s)
# r is ['AB', 'CD', 'EF']

【讨论】:

    【解决方案4】:

    完美的 Pythonic 并没有什么丑陋之处:

    string = 'ABCDXY'
    [string[i:i+2] for i in xrange(0, len(string), 2)]
    

    您还可以使用以下内容(来自 - http://docs.python.org/library/itertools.html):

    def grouper(n, iterable, fillvalue=None):
        "Collect data into fixed-length chunks or blocks"
        # grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx
        args = [iter(iterable)] * n
        return izip_longest(fillvalue=fillvalue, *args)
    

    (这取决于您如何看待它 - 可能会或可能不会使用“循环”;))

    或类似的东西:

    re.findall('..?', string)
    

    【讨论】:

    • +1 用于 zip 解决方案,其他答案均未提及。但它实际上返回 [(str, str), (str, str), ...],而不是 [str, str, ...],因此需要更多代码才能使其有用。
    • 另外,我见过的最方便的正则表达式使用!我最喜欢你的,因为它可以处理奇怪的长度。
    【解决方案5】:

    另一种解决方案,这个基于zip 和切片步幅:

    map(''.join, itertools.izip_longest(mystr[::2], mystr[1::2], fillvalue=''))
    

    它确实处理奇数长度的输入。

    【讨论】:

      【解决方案6】:

      这是另一个没有显式循环的解决方案(尽管@Emmanuel's answer is the most appropriate for your question):

      s = 'abcdef'
      L = zip(s[::2], s[1::2])
      # -> [('a', 'b'), ('c', 'd'), ('e', 'f')]
      

      获取字符串:

      print map(''.join, L)
      # ['ab', 'cd', 'ef']
      

      在 Python 3 上,必要时使用 list() 进行换行。

      【讨论】:

      • 厄运!我们俩同时在想zip
      猜你喜欢
      • 2016-01-16
      • 2011-08-28
      • 1970-01-01
      • 2016-12-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-24
      相关资源
      最近更新 更多