将一个字符串分成N个等份?

74

我有一个字符串,我想把它分成N个等份。

例如,假设我有一个长度为128的字符串,我想将其分成4个长度为32的块; 即前32个字符,然后是第二个32个字符,依此类推。

如何实现这个功能?


相关链接:https://dev59.com/lnVC5IYBdhLWcg3wYQAp - poke
6个回答

94
import textwrap
print(textwrap.wrap("123456789", 2))
#prints ['12', '34', '56', '78', '9']
注意:要小心空格等内容 - 这可能是你想要的,也可能不是。
"""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.
    """

请注意,在Python 3中,您需要将print放在括号中。 - Safwan Samsudeen
谁不知道在括号中包含打印语句呢? - Ecks Dee
你是否意识到有些人正在使用比你更古老的编程语言进行编程?甚至比Python 2更古老!(SCNR) - Volker Siegel

72

你可以使用一个简单的循环:

parts = [your_string[i:i+n] for i in range(0, len(your_string), n)]

36

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

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

这个方法直接来自于zip()的文档。


3
这比我的好多了!我可以借鉴这个以后使用吗? :) - Adam Smith
5
注意,"返回的列表将被截断为最短参数序列的长度",因此如果数据系列不能适配成等长的n个元素组,任何额外的元素都将被省略。 - None
那个 list 调用看起来是多余的;你为什么要添加它? - Air
1
@Air 在Python 2中,“map”函数返回一个列表,而在Python 3中返回一个生成器对象,这两种方式都可以正常工作。然而,考虑到本回答的目的,我认为使用列表会产生更好的输出结果。 - anon582847382
完美!使用':'.join(map(''.join, zip(*[reversed(qn.split('.'))]*4)))ip6.arpa.字符串进行转换。 - NiKiZe

7

递归方式:

def split_str(seq, chunk, skip_tail=False):
    lst = []
    if chunk <= len(seq):
        lst.extend([seq[:chunk]])
        lst.extend(split_str(seq[chunk:], chunk, skip_tail))
    elif not skip_tail and seq:
        lst.extend([seq])
    return lst

演示:

seq = "123456789abcdefghij"

print(split_str(seq, 3))
print(split_str(seq, 3, skip_tail=True))

# ['123', '456', '789', 'abc', 'def', 'ghi', 'j']
# ['123', '456', '789', 'abc', 'def', 'ghi']

序列的最大长度是多少?我收到了一个错误信息:“RecursionError:在调用Python对象时超过了最大递归深度”,其中包含约25k个字符。 - hi im vinzent

6
你可以在许多情况下将字符串类比于列表。这里有很多答案:将一个任意长度的列表分成大约N个相等的部分 例如,你可以计算出 chunk_size = len(my_string)/N
然后要访问一个块,你可以使用 my_string[i: i + chunk_size](然后逐步增加 i),可以在for循环或列表推导式中使用。

6

我喜欢迭代器!

def chunk(in_string,num_chunks):
    chunk_size = len(in_string)//num_chunks
    if len(in_string) % num_chunks: chunk_size += 1
    iterator = iter(in_string)
    for _ in range(num_chunks):
        accumulator = list()
        for _ in range(chunk_size):
            try: accumulator.append(next(iterator))
            except StopIteration: break
        yield ''.join(accumulator)

## DEMO
>>> string = "a"*32+"b"*32+"c"*32+"d"*32
>>> list(chunk(string,4))
['aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb', 'cccccccccccccccccccccccccccccccc', 'dddddddddddddddddddddddddddddddd']
>>> string += "e" # so it's not evenly divisible
>>> list(chunk(string,4))
['aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab', 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcc', 'ccccccccccccccccccccccccccccccddd', 'ddddddddddddddddddddddddddddde']

也明显比textwrap.wrap更快,尽管可能没那么"好"。
>>> timeit.timeit(lambda: list(chunk(string,4)),number=500)
0.047726927170444355
>>> timeit.timeit(lambda: textwrap.wrap(string,len(string)//4),number=500)
0.20812756575945457

这段代码非常容易与任何可迭代对象一起使用(只需删除str.join,并且在in_string不是字符串类型时不返回累加器即可)。

# after a petty hack
>>> list(chunk([1,2,3,4,5,6,7,8,9,10,11,12],4))
[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]

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