Python脚本在不同字符类型之间插入空格:为什么这么慢?

0 投票
6 回答
3619 浏览
提问于 2025-04-17 13:41

我正在处理一些混合语言的文本,这些文本我已经做了一些处理,现在是一个单个字符的列表(我们称这些字符为“字母”)。我可以通过一个小函数“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 是一个集合。

撰写回答