Python脚本在不同字符类型之间插入空格:为什么这么慢?
我正在处理一些混合语言的文本,这些文本我已经做了一些处理,现在是一个单个字符的列表(我们称这些字符为“字母”)。我可以通过一个小函数“test_lang”来判断每个字符属于哪种语言,方法是检查它是否有大小写。接下来,我想在不同类型的字符之间插入空格,这样就不会出现混合字符类型的单词。同时,我还想在单词和标点符号之间插入空格(我在一个名为“punc”的列表中定义了标点符号)。我写了一个脚本,以我认为很简单明了的方式来实现这个功能(见下文),但显然这是错误的方法,因为它运行得非常慢。
有没有人能告诉我更好的做法是什么?
# Add a space between Arabic/foreign mixes, and between words and punc
cleaned = ""
i = 0
while i <= len(letters)-2: #range excludes last letter to avoid Out of Range error for i+1
cleaned += letters[i]
# words that have case are Latin; otherwise Arabic
if test_lang(letters[i]) != test_lang(letters[i+1]):
cleaned += " "
if letters[i] in punc or letters[i+1] in punc:
cleaned += " "
i += 1
cleaned += letters[len(letters)-1] # add in last letter
6 个回答
1
我建议一个完全不同的解决方案,这个方法应该非常快:
import re
cleaned = re.sub(r"(?<!\s)\b(?!\s)", " ", letters, flags=re.LOCALE)
这个方法会在每个单词的边界插入一个空格(这里的单词定义为“由字母和数字组成的字符序列,包括你当前语言环境中的带重音的字符”,在大多数情况下应该都能正常工作),但如果边界旁边有空格就不插入。
这个方法可以在拉丁字母和阿拉伯字母之间,以及拉丁字母和标点符号之间进行分隔。
2
每次你把字符串连接在一起时,都会创建一个新的字符串。字符串越长,每次连接所花的时间就越长。
http://en.wikipedia.org/wiki/Schlemiel_the_Painter's_algorithm
你可能更好地选择先声明一个足够大的列表,用来存储最终输出的字符,然后在最后把它们连接起来。
4
这里有几个要点:
- 你对字符串中的每个字母调用了
test_lang()
两次,这可能是导致运行速度慢的主要原因。 - 在Python中,拼接字符串的效率不高,建议你使用列表或者生成器,然后再用
str.join()
(通常是''.join()
)来拼接。
我会采用以下方法,使用 itertools.groupby()
:
from itertools import groupby
def keyfunc(letter):
return (test_lang(letter), letter in punc)
cleaned = ' '.join(''.join(g) for k, g in groupby(letters, keyfunc))
这个方法会把字母分组,分成连续的相同语言的字母,以及标点符号,然后 ''.join(g)
会把每组字母再转换回字符串,接着 ' '.join()
会把这些字符串合并在一起,中间加一个空格。
另外,正如DSM在评论中提到的,确保 punc
是一个集合。