对于Python,除了a-z、a-z、0-9、z和-,从字符串中删除所有字符的最有效方法是什么?

对于Python,除了a-z、a-z、0-9、z和-,从字符串中删除所有字符的最有效方法是什么?,python,regex,string,formatting,Python,Regex,String,Formatting,注意:最大字符串长度为15个字符。为了比较原始速度,这里比较了一些优化和正则表达式解决方案: import re, string, timeit clean = re.compile(r'[^a-zA-Z0-9_-]') keep = string.ascii_letters + string.digits + '_-' keep_set = set(string.ascii_letters + string.digits + '_-') test = '$pam and_Eggs##-!'

注意:最大字符串长度为15个字符。

为了比较原始速度,这里比较了一些优化和正则表达式解决方案:

import re, string, timeit

clean = re.compile(r'[^a-zA-Z0-9_-]')
keep = string.ascii_letters + string.digits + '_-'
keep_set = set(string.ascii_letters + string.digits + '_-')
test = '$pam and_Eggs##-!'
cur_encoding_bytes = 256 # 8 for UTF-8, in Python 3 this would be different for Unicode
all_else = ''.join(chr(i) for i in range(cur_encoding_bytes) if chr(i) not in keep_set) # taken from https://stackoverflow.com/a/3588485/1219006

def clean1(s):
    return ''.join(x for x in s if x in keep)

def clean1_filter(s):
    return filter(keep.__contains__, s)

def clean1_filter_set(s):
    return filter(keep_set.__contains__, s)

def clean2(s):
    return clean.sub('', s)

def clean3(s):
    return s.translate(None, all_else)

print timeit.timeit('clean1(test)', 'from __main__ import clean1, test')
print timeit.timeit('clean1_filter(test)', 'from __main__ import clean1_filter, test')
print timeit.timeit('clean1_filter_set(test)', 'from __main__ import clean1_filter_set, test')
print timeit.timeit('clean2(test)', 'from __main__ import clean2, test')
print timeit.timeit('clean3(test)', 'from __main__ import clean3, test')
此脚本的输出为:

2.96962522809
1.56208783165
1.10597814849
1.59298783663
0.53834820236

str.translate是最快的,是一种专门的字符串方法。

ya ya,有很多这样的问题,但它们似乎不是“最有效的”或最佳处理方法的“确定”答案。@chrickso:对于长度为15的字符串,即使是一个简单的算法也会非常快。@chrickso:如果你问的是我见过的这几种方法中哪一种更快,那么你至少可以列举一些方法,这些方法也表明你做过研究。当然,一旦你完成了这项工作,你就可以自己计算方法的时间了。@chrickso除非你把“效率”误认为是原始速度,否则任何解决方案都可以高效运行,15个字符可以在极快的时间内处理,因此效率其实并不重要。如果你为了微优化而问哪个解决方案最快,那将是一个更好的问题,尽管微优化很少需要。把keep变成一个集合,它就会更接近。@Blender我做了一组更全面的测试,表明正则表达式不是最快的,而通常不是最快的。@jamylak:谢谢你的。u包含uu函数,我从来不知道这件事。我尝试了lambda,但它的性能比常规的列表理解更差。@jamylak:我从未意识到筛选器会为字符串参数返回字符串。@Blender:\uuuuuu contains\uuuuuu只是中的实现。我不会想到将它与过滤器一起使用。
>>> def clean(s):
...   from string import ascii_letters, digits
...   keep = ascii_letters + digits + '_-'
...   return ''.join(x for x in s if x in keep)
... 
>>> clean('$pam and_Eggs##-!')
'pamand_Eggs-'