按长度将字符串拆分成多个字符串?

82

有没有一种方法可以将一个长度为4*x的字符串切成4个长度为x个字符的子串,而不需要知道字符串的长度?

例如:

>>>x = "qwertyui"
>>>split(x, one, two, three, four)
>>>two
'er'

3
你不能只是用 len(x) 来获取字符串的长度吗? - Eric
Eric:那你怎么使用它呢? - tkbx
3
可能是 Split string every nth character? 的重复问题。 - mkrieger1
16个回答

120
>>> x = "qwertyui"
>>> chunks, chunk_size = len(x), len(x)//4
>>> [ x[i:i+chunk_size] for i in range(0, chunks, chunk_size) ]
['qw', 'er', 'ty', 'ui']

16
设置 chunks 的价值是什么?它将始终为 x 的长度。 - Nitay
这是为了可读性。 - Alexander
textwrap.wrap 更加方便 - textwrap.wrap(x, width=2, break_long_words=True, drop_whitespace=False, replace_whitespace=False) - Shekhar Samanta
4
这是为了可读性。我非常支持可读性,但是将len(x)称为“chunks”并不支持这个目标。 “chunks”的名称是“块数”,对吧?所以它应该设置为4。如果你想给len(x)命名,就把它命名为“length”。 - MarredCheese
我也不认为“length”更好 - Alexander

27

26

我尝试了Alexanders的答案,但在Python3中遇到了这个错误:

TypeError:'float'对象无法解释为整数

这是因为Python3中的除法运算符返回一个浮点数。这对我有用:

>>> x = "qwertyui"
>>> chunks, chunk_size = len(x), len(x)//4
>>> [ x[i:i+chunk_size] for i in range(0, chunks, chunk_size) ]
['qw', 'er', 'ty', 'ui']

注意第2行末尾的//,以确保截断为整数。


4
你可能正在使用Python3,在这个版本中,除法符号返回一个浮点数。你可以使用截断除法符号//来代替强制转换为整数:len(x)//4。此外,我认为在int(len(x))中的强制转换是不必要的。 - BoppreH
我想出了一个将我的文本分成两部分的答案,但是如果你将 len(x)//4 改为 len(x)//2,代码会将其分成 3 部分。所以我在 len(x)//2 的末尾添加了 +1。希望这对你们中的任何人有帮助。 - Kemal Can Kara

13
some_string="ABCDEFGHIJKLMNOPQRSTUVWXYZ"
x=3 
res=[some_string[y-x:y] for y in range(x, len(some_string)+x,x)]
print(res)

将产生

['ABC', 'DEF', 'GHI', 'JKL', 'MNO', 'PQR', 'STU', 'VWX', 'YZ']

12

在除了娱乐场合之外,由于性能原因,应该避免这样做。 - Reinderien

7
def split2len(s, n):
    def _f(s, n):
        while s:
            yield s[:n]
            s = s[n:]
    return list(_f(s, n))

3
你能解释一下你的答案吗? - Zulu

7
这里有一个不需要预先知道字符串长度的一行代码:
from functools import partial
from StringIO import StringIO

[l for l in iter(partial(StringIO(data).read, 4), '')]

如果你有一个文件或套接字,那么你不需要使用StringIO包装器:
[l for l in iter(partial(file_like_object.read, 4), '')]

如果你正在使用Python3,StringIO现在在io模块中。 - Marcelo Lacerda

4

学会了一个有关re的技巧:

In [28]: import re

In [29]: x = "qwertyui"

In [30]: [x for x in re.split(r'(\w{2})', x) if x]
Out[30]: ['qw', 'er', 'ty', 'ui']

然后定义一个函数,它可能看起来像这样:
def split(string, split_len):
    # Regex: `r'.{1}'` for example works for all characters
    regex = r'(.{%s})' % split_len
    return [x for x in re.split(regex, string) if x]

这很有趣。这个带有分割的正则表达式是如何工作的,为什么会产生前导和后继的空匹配? - Bill
顺便提一下,你也可以这样做:list(filter(None, re.split(r'(\w{2})', x))) - Bill
1
这个方法似乎也可以并且更简单:re.findall(r'(\w{2})', x) - Bill

1
length = 4
string = "abcdefgh"
str_dict = [ o for o in string ]
parts = [ ''.join( str_dict[ (j * length) : ( ( j + 1 ) * length ) ]   ) for j in xrange(len(string)/length  )]

嗨,Frederico,欢迎来到SO!解释一下你在这个答案中为什么这样做可能是值得的,这样那些对你展示的语言和思想感到陌生的新手可以理解为什么这是采取的好行动方针。 - Ethan Field

1
这里有两种通用方法。可能值得添加到您自己的可重用库中。第一种需要对项进行切片,第二种适用于任何可迭代对象(但需要它们的构造函数接受可迭代对象)。
def split_bylen(item, maxlen):
    '''
    Requires item to be sliceable (with __getitem__ defined)
    '''
    return [item[ind:ind+maxlen] for ind in range(0, len(item), maxlen)]
    #You could also replace outer [ ] brackets with ( ) to use as generator.

def split_bylen_any(item, maxlen, constructor=None):
    '''
    Works with any iterables.
    Requires item's constructor to accept iterable or alternatively 
    constructor argument could be provided (otherwise use item's class)
    '''
    if constructor is None: constructor = item.__class__
    return [constructor(part) for part in zip(* ([iter(item)] * maxlen))]
    #OR: return map(constructor, zip(* ([iter(item)] * maxlen)))
    #    which would be faster if you need an iterable, not list

所以,在主题发起者的情况下,使用方法是:

string = 'Baboons love bananas'
parts = 5
splitlen = -(-len(string) // parts) # is alternative to math.ceil(len/parts)

first_method = split_bylen(string, splitlen)
#Result :['Babo', 'ons ', 'love', ' ban', 'anas']

second_method = split_bylen_any(string, splitlen, constructor=''.join)
#Result :['Babo', 'ons ', 'love', ' ban', 'anas']

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