我们可以使用以下符号对字符串中的连续字符进行重复数据删除:
def deduplicate(string, char):
return char.join([substring for substring in string.strip().split(char) if substring])
E.g。
>>> s = 'this is an irritating string with random spacing .'
>>> deduplicate(s)
'this is an irritating string with random spacing .'
在命令行中,squeeze
有一个tr
选项:
$ tr -s " " < file
Python的字符串中是否有squeeze
函数?
在Python中对字符串中的连续字符进行重复数据删除的最快方法是什么?
请注意,要进行重复数据删除的字符应该是任何ascii / unicode字符,而不仅仅是\s
/ whitespace。 (ascii和unicode有2个子答案,这很好。
答案 0 :(得分:3)
Itertools是一个很好的尝试
>>> t = "THHHISSS ISSS BBBBSSSSS"
>>> import itertools
>>> ''.join(char for char, _ in itertools.groupby(t))
'THIS IS BS'
答案 1 :(得分:2)
首先,您的deduplicate
功能实际上非常快。但是可以进行一些改进以使其更快。我lambda
了你的功能并将其称为org_deduplicate
(下方)。现在进行一些时间测试(使用iPython&#39; s %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
它可以加快速度,但并不是那么令人印象深刻。让我们尝试一种不同的方法......正则表达式。这些也很好,因为它们可以灵活地选择任何正则表达式作为你的#34;字符&#34;重复数据删除(不只是一个字符):
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
函数更快。如果我们尝试压缩(如果使用Python 2,则使用itertools.izip
)该怎么办:
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
当要删除多个重复字符串时,它确实失去了一些优势。
总之,如果您的字符串具有重复字符的长子串,请使用您的原始函数(可能会进行一些调整)。否则,递归版本最快。