是否有可能分割字符串每n个字符?

例如,假设我有一个包含以下内容的字符串:

'1234567890'

我怎样才能让它看起来像这样:

['12','34','56','78','90']

关于列表的相同问题,请参见如何将列表分割为大小相等的块?。同样的技术通常适用,尽管有一些变化。


当前回答

使用PyPI中的更多itertools:

>>> from more_itertools import sliced
>>> list(sliced('1234567890', 2))
['12', '34', '56', '78', '90']

其他回答

more_itertools。切片之前提到过。下面是more_itertools库中的另外四个选项:

s = "1234567890"

["".join(c) for c in mit.grouper(2, s)]

["".join(c) for c in mit.chunked(s, 2)]

["".join(c) for c in mit.windowed(s, 2, step=2)]

["".join(c) for c in  mit.split_after(s, lambda x: int(x) % 2 == 0)]

后面的每个选项都会产生以下输出:

['12', '34', '56', '78', '90']

所讨论选项的文档:grouper, chunked, windosed, split_after

短字符串的简单递归解决方案:

def split(s, n):
    if len(s) < n:
        return []
    else:
        return [s[:n]] + split(s[n:], n)

print(split('1234567890', 2))

或以这样的形式:

def split(s, n):
    if len(s) < n:
        return []
    elif len(s) == n:
        return [s]
    else:
        return split(s[:n], n) + split(s[n:], n)

,它更明确地说明了递归方法中的典型分治模式(尽管实际上没有必要这样做)。

试试这个:

s='1234567890'
print([s[idx:idx+2] for idx,val in enumerate(s) if idx%2 == 0])

输出:

['12', '34', '56', '78', '90']

这些答案都很好,很有用,但是语法太神秘了……为什么不写一个简单的函数呢?

def SplitEvery(string, length):
    if len(string) <= length: return [string]        
    sections = len(string) / length
    lines = []
    start = 0;
    for i in range(sections):
        line = string[start:start+length]
        lines.append(line)
        start += length
    return lines

简单地叫它:

text = '1234567890'
lines = SplitEvery(text, 2)
print(lines)

# output: ['12', '34', '56', '78', '90']

为了完整,你可以用regex来完成:

>>> import re
>>> re.findall('..','1234567890')
['12', '34', '56', '78', '90']

对于奇数个字符,你可以这样做:

>>> import re
>>> re.findall('..?', '123456789')
['12', '34', '56', '78', '9']

你也可以这样做,简化正则表达式为更长的块:

>>> import re
>>> re.findall('.{1,2}', '123456789')
['12', '34', '56', '78', '9']

如果字符串很长,可以使用re.finditer逐块生成。