每n个字符分割一个字符串?


Answers:


549
>>> line = '1234567890'
>>> n = 2
>>> [line[i:i+n] for i in range(0, len(line), n)]
['12', '34', '56', '78', '90']

35
这是一个非常不错的答案,因为它不会以任何方式缠绕,并且由于其简单性,您可以轻松记住该方法
Trevor Rudolph 2014年

1
@TrevorRudolph它只是完全按照您所说的去做。上面的答案实际上只是一个for循环,而是用Python表达的。另外,如果您需要记住一个“简单化”的答案,则至少有成千上万种方法可以记住它们:在stackoverflow上为页面加注星标;复制然后粘贴到电子邮件中;用您想记住的东西保存一个“有用的”文件;只需在需要时使用现代搜索引擎;在(可能)每个网络浏览器中使用书签;等
dylnmc

1
然而,在第二点上,您似乎认真的。实际上,我希望您是认真的,因为这确实令人费解。
dylnmc 2014年

1
我是认真的,我在模拟器的二进制转换器中使用了此代码,我喜欢它是用于循环哈哈的pythonic语言,但感谢您进一步分解为什么我喜欢这种方法!
特雷弗·鲁道夫

5
具有讽刺意味的是,试图以没有隐藏含义的方式使用单词,通常会导致句子混乱。
deed02392

207

为了完整起见,您可以使用正则表达式执行此操作:

>>> 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如果字符串很长,则可以使用它逐块生成。


3
到目前为止,这是最好的答案,应该放在首位。一个人甚至可以写得'.'*n更清楚。没有加入,没有压缩,没有循环,没有列表理解;只需找到彼此相邻的下两个字符,这正是人脑对此的思考。如果Monty Python还活着,他一定会喜欢这种方法!
jdk1.0

这也是处理相当长的字符串的最快方法:gitlab.com/snippets/1908857
Ralph Bolton

如果字符串包含换行符,则此方法将无效。这需要flags=re.S
阿兰·菲

ahhh .... regex ....为什么我没有想到那个XD
PizzaGuy先生

146

在python中已经有一个内置函数。

>>> from textwrap import wrap
>>> s = '1234567890'
>>> wrap(s, 2)
['12', '34', '56', '78', '90']

这是wrap的文档字符串所说的:

>>> help(wrap)
'''
Help on function wrap in module textwrap:

wrap(text, width=70, **kwargs)
    Wrap a single paragraph of text, returning a list of wrapped lines.

    Reformat the single paragraph in 'text' so it fits in lines of no
    more than 'width' columns, and return a list of wrapped lines.  By
    default, tabs in 'text' are expanded with string.expandtabs(), and
    all other whitespace characters (including newline) are converted to
    space.  See TextWrapper class for available keyword args to customize
    wrapping behaviour.
'''

2
print(wrap('12345678',3))将字符串分成3位数字的组,但是从前面开始而不是从后面开始。结果:['123','456','78']
阿塔兰托雷

2
了解“包装”很有趣,但它并没有完全按照上面的要求进行。它更倾向于显示文本,而不是将字符串拆分为固定数量的字符。
Oren

2
wrap可能不会返回字符串是否包含空格的要求。例如wrap('0 1 2 3 4 5', 2)回报['0', '1', '2', '3', '4', '5'](元素被剥离)
satomacoto

3
这确实回答了这个问题,但是如果有空格并且您希望将它们保留在拆分字符中,会发生什么情况?wrap()会删除空格,如果空格在一组字符分割之后掉落
Iron Attorney

1
如果您想用连字符来分隔文本,则效果不佳(作为参数给出的数字实际上是最大字符数,而不是精确的字符数,并且会折断,即在连字符和空白处)。
MrVocabulary

80

将元素分组为n个长度的组的另一种常见方式:

>>> s = '1234567890'
>>> map(''.join, zip(*[iter(s)]*2))
['12', '34', '56', '78', '90']

此方法直接来自的文档zip()


2
在[19]中:a =“ hello world”; list(map(“” .join,zip(* [iter(a)] * 4))))得到结果['hell','o wo']。
truease.com 2013年

16
如果有人觉得zip(*[iter(s)]*2)难以理解,请阅读如何zip(*[iter(s)]*n)在Python 中工作?
2014年

15
这不会说明字符的奇数,它只会删除这些字符:>>> map(''.join, zip(*[iter('01234567')]*5))->['01234']
Bjorn 2014年

3
要同时处理奇数个字符,只需替换zip()itertools.zip_longest()map(''.join, zip_longest(*[iter(s)]*2, fillvalue=''))
Paulo Freitas

也有用:的文档maps()
winklerrr '19

57

我认为这比itertools版本更短,更易读:

def split_by_n(seq, n):
    '''A generator to divide a sequence into chunks of n units.'''
    while seq:
        yield seq[:n]
        seq = seq[n:]

print(list(split_by_n('1234567890', 2)))

7
但效率并不高:应用于字符串时:副本过多
Eric

1
如果seq是生成器,则它也不起作用,这是itertools版本的用途。并不是OP要求这样做,但是批评itertool的版本不那么简单是不公平的。
CryingCyclops

24

我喜欢这个解决方案:

s = '1234567890'
o = []
while s:
    o.append(s[:2])
    s = s[2:]

24

使用PyPI的more-itertools

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

11

您可以使用以下grouper()配方itertools

Python 2.x:

from itertools import izip_longest    

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

Python 3.x:

from itertools import zip_longest

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

这些函数可节省内存,并且可与任何可迭代对象一起使用。


5

尝试以下代码:

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)它来使其按预期的方式运行:eval.in/813878
Paulo Freitas

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

3

尝试这个:

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

输出:

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

2

一如既往,对于那些喜欢一只班轮的人

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中用a运行时,print(line)得到this is a line split into n characters输出。你可能会更好地投入:line = [line[i * n:i * n+n] for i,blah in enumerate(line[::n])]?解决这个问题,这是一个很好的答案:)。
Google搜索的内容是

您能解释,blah为何以及为什么有必要吗?我注意到我可以blah用任何字母字符代替,但不能用数字代替,并且不能删除blahor或逗号。我的编辑建议在,:s 之后添加空格
toonarmycaptain

enumerate返回两个可迭代对象,因此您需要两个位置放置它们。但是在这种情况下,您实际上不需要任何东西的第二个可迭代对象。
丹尼尔·F

1
blah我更喜欢使用下划线或双下划线,请参阅:stackoverflow.com/questions/5893163/...
安迪皇家

1

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

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)

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


1

我陷入了同一个场景。

这对我有用

x="1234567890"
n=2
list=[]
for i in range(0,len(x),n):
    list.append(x[i:i+n])
print(list)

输出量

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

0

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


-1

这可以通过简单的for循环来实现。

a = '1234567890a'
result = []

for i in range(0, len(a), 2):
    result.append(a[i : i + 2])
print(result)

输出看起来像['12','34','56','78','90','a']


2
尽管此代码可以回答问题,但提供有关此代码为何和/或如何回答问题的其他上下文,可以改善其长期价值。
β.εηοιτ.βε

2
这是与此处相同的解决方案:stackoverflow.com/a/59091507/7851470
Georgy
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.