Любопытно, что по моим собственным причинам я написал быстрый скрипт для проверки различных подходов, перечисленных здесь, а также простое удаление лямбды, которое, как я ожидал (неправильно), ускорит исходное решение.
Короткая версия заключается в том, что подход str.translate отбрасывает другие. Кроме того, решение регулярных выражений, хотя и близкая секунда, является правильным, как написано выше.
Вот моя тестовая программа:
import re
from time import time
def format_title(title):
return ''.join(map(lambda x: x if (x.isupper() or x.islower()) else "_",
title.strip()))
def format_title_list_comp(title):
return ''.join([x if x.isupper() or x.islower() else "_" for x in
title.strip()])
def format_title_list_comp_is_alpha(title):
return ''.join([x if x.isalpha() else "_" for x in title.strip()])
def format_title_is_alpha(title):
return ''.join(map(lambda x: x if x.isalpha() else '_', title.strip()))
def format_title_no_lambda(title):
def trans(c):
if c.isupper() or c.islower():
return c
return "_"
return ''.join(map(trans, title.strip()))
def format_title_no_lambda_is_alpha(title):
def trans(c):
if c.isalpha():
return c
return "_"
return ''.join(map(trans, title.strip()))
def format_title_re(title):
return re.sub("[\W\d]+", "_", title.strip())
def format_title_re_corrected(title):
return re.sub("[\W\d]", "_", title.strip())
TITLE_TRANS = ''.join(chr(c) if chr(c).isalpha() else '_' for c in range(256))
def format_title_with_translate(title):
return title.translate(TITLE_TRANS)
ITERATIONS = 200000
EXAMPLE_TITLE = "abc123def_$%^!FOO BAR*bazx-bif"
def timetest(f):
start = time()
for i in xrange(ITERATIONS):
result = f(EXAMPLE_TITLE)
diff = time() - start
return result, diff
baseline_result, baseline_time = timetest(format_title)
def print_result(f, result, time):
if result == baseline_result:
msg = "CORRECT"
else:
msg = "INCORRECT"
diff = time - baseline_time
if diff < 0:
indicator = ""
else:
indicator = "+"
pct = (diff / baseline_time) * 100
print "%s: %0.3fs %s%0.3fs [%s%0.4f%%] (%s - %s)" % (
f.__name__, time, indicator, diff, indicator, pct, result, msg)
print_result(format_title, baseline_result, baseline_time)
print "----"
for f in [format_title_is_alpha,
format_title_list_comp,
format_title_list_comp_is_alpha,
format_title_no_lambda,
format_title_no_lambda_is_alpha,
format_title_re,
format_title_re_corrected,
format_title_with_translate]:
alt_result, alt_time = timetest(f)
print_result(f, alt_result, alt_time)
А вот и результаты:
format_title: 3.121s +0.000s [+0.0000%] (abc___def_____FOO_BAR_bazx_bif - CORRECT)
----
format_title_is_alpha: 2.336s -0.785s [-25.1470%] (abc___def_____FOO_BAR_bazx_bif - CORRECT)
format_title_list_comp: 2.369s -0.751s [-24.0773%] (abc___def_____FOO_BAR_bazx_bif - CORRECT)
format_title_list_comp_is_alpha: 1.735s -1.386s [-44.4021%] (abc___def_____FOO_BAR_bazx_bif - CORRECT)
format_title_no_lambda: 2.992s -0.129s [-4.1336%] (abc___def_____FOO_BAR_bazx_bif - CORRECT)
format_title_no_lambda_is_alpha: 2.377s -0.744s [-23.8314%] (abc___def_____FOO_BAR_bazx_bif - CORRECT)
format_title_re: 1.290s -1.831s [-58.6628%] (abc_def__FOO_BAR_bazx_bif - INCORRECT)
format_title_re_corrected: 1.338s -1.782s [-57.1165%] (abc___def_____FOO_BAR_bazx_bif - CORRECT)
format_title_with_translate: 0.098s -3.022s [-96.8447%] (abc___def_____FOO_BAR_bazx_bif - CORRECT)
- РЕДАКТИРОВАНИЕ: Я добавил вариант, который показывает, что понимание списка значительно улучшает исходную реализацию, а также правильную реализацию регулярных выражений, которая показывает, что при правильной работе она все еще почти так же быстра Конечно, str.translate по-прежнему выигрывает руки.