每隔n个字符拆分字符串

601
19个回答

10

试试这个:

s = '1234567890'
print([s[idx:idx+2] for idx in range(len(s)) if idx % 2 == 0])

输出:

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

1
为什么对枚举对象 s 进行枚举而忽略其值?直接用 for i in range(len(s)) 即可。为什么要遍历每个值然后扔掉一半?直接跳过不需要的值:for i in range(0, len(s), 2)(省略 if 部分)。 - Arthur Tacca

8
尝试以下代码:
from itertools import islice

def split_every(n, iterable):
    i = iter(iterable)
    piece = list(islice(i, n))
    while piece:
        yield piece
        piece = list(islice(i, n))

s = '1234567890'
print list(split_every(2, list(s)))

你的回答不符合 OP 的要求,你必须使用 yield ''.join(piece) 才能使其按预期工作:https://eval.in/813878 - Paulo Freitas

6
>>> from functools import reduce
>>> from operator import add
>>> from itertools import izip
>>> x = iter('1234567890')
>>> [reduce(add, tup) for tup in izip(x, x)]
['12', '34', '56', '78', '90']
>>> x = iter('1234567890')
>>> [reduce(add, tup) for tup in izip(x, x, x)]
['123', '456', '789']

6

对于那些喜欢一行代码的人,像往常一样:

n = 2  
line = "this is a line split into n characters"  
line = [line[i * n:i * n+n] for i, blah in enumerate(line[::n])]

当我在 Python Fiddle 中运行这段代码并使用 print(line) 时,输出是 this is a line split into n characters。你可能会更好地将代码改为:line = [line[i * n:i * n+n] for i,blah in enumerate(line[::n])]。修复此问题后,它将成为一个不错的答案 :)。 - Peter David Carter
你能解释一下 ,blah 并说明它的必要性吗?我注意到我可以用任何字母替换 blah,但不能使用数字,并且不能删除 ,blah 或/和逗号。我的编辑器建议在 , 后添加空格 :s - toonarmycaptain
“enumerate”返回两个可迭代对象,因此您需要两个位置来放置它们。但在这种情况下,实际上您不需要第二个可迭代对象。 - Daniel F
1
与其使用“blah”,我更喜欢使用下划线或双下划线,参见:https://dev59.com/AW025IYBdhLWcg3wpHh- - Andy Royal

3

more_itertools.sliced曾经提到过。这里还有来自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']

讨论选项的文档:grouperchunkedwindowedsplit_after


3
一个简单的递归解决方案,适用于短字符串:
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)

这段内容更加明确地展示了递归方法中典型的分治模式(尽管实际上没有必要这样做)


3
一种使用groupby的解决方案:
from itertools import groupby, chain, repeat, cycle

text = "wwworldggggreattecchemggpwwwzaz"
n = 3
c = cycle(chain(repeat(0, n), repeat(1, n)))
res = ["".join(g) for _, g in groupby(text, lambda x: next(c))]
print(res)

输出:

['www', 'orl', 'dgg', 'ggr', 'eat', 'tec', 'che', 'mgg', 'pww', 'wza', 'z']

0

这些答案都很好,而且也都能用,但是语法太晦涩了... 为什么不写一个简单的函数呢?

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']

1
你不能将浮点数传递给range函数,因此你展示的函数不会工作。(如果你不相信我,请尝试运行它) - cd-CreepArghhh

0

另一种解决方案是使用groupbyindex//n作为键来分组字母:

from itertools import groupby

text = "abcdefghij"
n = 3

result = []
for idx, chunk in groupby(text, key=lambda x: x.index//n):
    result.append("".join(chunk))

# result = ['abc', 'def', 'ghi', 'j']

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接