对字符串中的连续字符进行重复数据删除的最快方法-Python [duplicate]
问题内容:
这个问题已经在这里有了答案 :
Python:从字符串中删除重复字符的最佳方法 (7个答案)
3年前关闭。
我们可以使用以下方法对字符串中的连续字符进行重复数据删除:
def deduplicate(string, char):
return char.join([substring for substring in string.strip().split(char) if substring])
例如
>>> s = 'this is an irritating string with random spacing .'
>>> deduplicate(s)
'this is an irritating string with random spacing .'
在命令行上有一个squeeze
选项tr
:
$ tr -s " " < file
squeeze
Python的字符串中有函数吗?
在Python中对字符串中的重复字符进行重复数据删除的最快方法是什么?
请注意,要删除重复数据的字符应该是任意ascii / unicode字符,而不仅仅是\s
/空格。(最好为ascii和unicode提供2个子答案。
问题答案:
首先,您的deduplicate
功能实际上非常快。但是可以进行一些改进以使其更快。我已经确定了lambda
您的函数并对其进行了命名org_deduplicate
(如下)。现在进行一些时间测试(使用iPython的%timeit
):
s = 'this is an irritating string with random spacing .'
org_deduplicate = lambda s,c: c.join([substring for substring in s.strip().split(c) if substring])
%timeit org_deduplicate(s,' ')
100000 loops, best of 3: 3.59 µs per loop
但strip
实际上并不是必须的,甚至可能会给您带来意想不到的结果(如果您不对空白进行重复数据删除),那么我们可以尝试:
org_deduplicate2 = lambda s,c: c.join(substring for substring in s.split(c) if substring)
%timeit org_deduplicate2(s,' ')
100000 loops, best of 3: 3.4 µs per loop
可以加快速度,但效果却不尽如人意。让我们尝试另一种方法…正则表达式。这些也很不错,因为它们使您可以灵活地选择任何正则表达式作为要进行重复数据删除的“字符”(不仅是单个字符):
import re
re_deduplicate = lambda s,c: re.sub(r'(%s)(?:\1)+' %c, '\g<1>', s)
re_deduplicate2 = lambda s,c: c.join(re.split('%s+'%c,s))
%timeit re_deduplicate(s,' ')
100000 loops, best of 3: 13.8 µs per loop
%timeit re_deduplicate2(s,' ')
100000 loops, best of 3: 6.47 µs per loop
第二个速度更快,但是都没有一个接近您的原始功能。看起来常规的字符串操作比re
函数更快。如果我们改为尝试压缩(itertools.izip
与Python
2配合使用,该怎么办):
zip_deduplicate = lambda s,c: ''.join(s1 for s1,s2 in zip(s,s[1:]) if s1!=c or s1!=s2)
%timeit zip_deduplicate(s,' ')
100000 loops, best of 3: 12.9 µs per loop
仍然没有改善。zip方法产生过多的子字符串,这会使执行''.join
速度变慢。好的,再尝试一次…str.replace
递归调用:
def rec_deduplicate(s,c):
if s.find(c*2) != -1:
return rec_deduplicate(s.replace(c*2, c),c)
return s
%timeit rec_deduplicate(s,' ')
100000 loops, best of 3: 2.83 µs per loop
不错,这似乎是我们的赢家。但是可以肯定的是,让我们用一个很长的输入字符串来对我们的原始函数进行尝试:
s2 = s*100000
%timeit rec_deduplicate(s2,' ')
10 loops, best of 3: 64.6 ms per loop
%timeit org_deduplicate(s2,' ')
1 loop, best of 3: 209 ms per loop
是的,看起来可以很好地缩放。但是让我们再进行一次测试,递归重复数据删除器每次调用时只会删除长度为2的重复字符。因此,对于长时间重复的字符,它是否仍然做得更好:
s3 = 'this is an irritating string with random spacing .'
%timeit rec_deduplicate(s3,' ')
100000 loops, best of 3: 9.93 µs per loop
%timeit org_deduplicate(s3,' ')
100000 loops, best of 3: 8.99 µs per loop
当要删除的重复字符串很长时,它确实失去了一些优势。
总之,如果您的字符串中包含重复字符的长子字符串,请使用原始函数(可能会进行一些调整)。否则,递归版本是最快的。