将字符串分割成固定长度的块并在 Python 中使用它们的最佳方法是什么?

问题描述 投票:0回答:8

我正在使用以下方式从文本文件中读取一行:

   file = urllib2.urlopen("http://192.168.100.17/test.txt").read().splitlines()

并在 telnetlib.write 命令中将其输出到 LCD 显示屏(16 个字符宽)。 如果读取的行长度超过 16 个字符,我想将其分解为 16 个字符长字符串的部分,并在一定延迟(例如 10 秒)后将每个部分推出,一旦完成,代码应移至下一行输入文件并继续。

我尝试过搜索各种解决方案并阅读 itertools 等,但我对 Python 的理解不足以让任何事情正常工作,除非使用一堆混乱的 if then else 语句以非常冗长的方式进行操作,这可能是会让我陷入困境!

对我来说,做我想做的事情的最佳方式是什么?

python
8个回答
81
投票

一种解决方案是使用此功能:

def chunkstring(string, length):
    return (string[0+i:length+i] for i in range(0, len(string), length))

此函数使用生成器理解返回一个生成器。生成器返回切片后的字符串,从 0 + 块长度的倍数到块长度 + 块长度的倍数。

您可以像列表、元组或字符串一样迭代生成器 -

for i in chunkstring(s,n):
,或者使用
list(generator)
将其转换为列表(例如)。生成器比列表具有更高的内存效率,因为它们根据需要生成元素,而不是一次性生成所有元素,但是它们缺乏索引等某些功能。

该生成器末尾还包含任何较小的块:

>>> list(chunkstring("abcdefghijklmnopqrstuvwxyz", 5))
['abcde', 'fghij', 'klmno', 'pqrst', 'uvwxy', 'z']

使用示例:

text = """This is the first line.
           This is the second line.
           The line below is true.
           The line above is false.
           A short line.
           A very very very very very very very very very long line.
           A self-referential line.
           The last line.
        """

lines = (i.strip() for i in text.splitlines())

for line in lines:
    for chunk in chunkstring(line, 16):
        print(chunk)

12
投票

标准库提供了 textwrap.wrap:

from textwrap import wrap

s = "some random text that should be splitted into chunks"

print(wrap(s, width=3))

['som', 'e r', 'and', 'om ', 'tex', 't t', 'hat', 'sho', 'uld', 'be ', 'spl', 
 'itt', 'ed ', 'int', 'o c', 'hun', 'ks']

10
投票

我最喜欢的解决此问题的方法是使用

re
模块。

import re

def chunkstring(string, length):
  return re.findall('.{%d}' % length, string)

这里需要注意的是,

re.findall
不会返回小于长度值的块,因此会跳过任何剩余部分。

但是,如果您要解析固定宽度的数据,这是一个很好的方法。

例如,如果我想解析我知道由 32 字节字符组成的文本块(如标题部分),我发现这非常可读,并且不需要将其概括为单独的函数(如

chunkstring中所示) 
):

for header in re.findall('.{32}', header_data):
  ProcessHeader(header)

4
投票

用列表理解来做:

n = "aaabbbcccddd"
k = 3
[n[i:i+k] for i in range(0,len(n),k)]
=> ['aaa', 'bbb', 'ccc', 'ddd']

3
投票

我知道这是一个老歌,但想添加如何用可变长度列切碎字符串:

def chunkstring(string, lengths):
    return (string[pos:pos+length].strip()
            for idx,length in enumerate(lengths)
            for pos in [sum(map(int, lengths[:idx]))])

column_lengths = [10,19,13,11,7,7,15]
fields = list(chunkstring(line, column_lengths))

2
投票

我认为这种方式更容易阅读:

string = "when an unknown printer took a galley of type and scrambled it to make a type specimen book."
length = 20
list_of_strings = []
for i in range(0, len(string), length):
    list_of_strings.append(string[i:length+i])
print(list_of_strings)

0
投票

变得更加简单:

str_to_split="KIMJEONG" # Your string to split here
n=4 # Your chunk length here
buf=""
ourchunks=[]
x=0

for i in str_to_split:
   x += 1
   buf += i
   if (x % 4) == 0:
     ourchunks.append(buf)
     buf=""

0
投票

您可以使用

itertools
现在(自 2023 年 10 月起(

Python 3.12+

import itertools

s = "QVQLVQ TVL QVQLVQSGC"

'\n'.join(
  [''.join(t) for t in itertools.batched(s, 4)]
)

对于 3.12 之前的 Python 版本,您只需复制粘贴 [正版

batched
实现][1]:

的缩短版本
def batched(iterable, chunk_size):
    items = iter(iterable)
    while batch := tuple(itertools.islice(items, chunk_size)):
        yield batch
© www.soinside.com 2019 - 2024. All rights reserved.