Во-первых, я хочу согласиться с другими, что регулярные выражения или str.translate(...)
основанные на них решения наиболее эффективны. Для моего варианта использования производительность этой функции была незначительной, поэтому я хотел добавить идеи, которые я рассмотрел, с помощью этих критериев.
Моя главная цель состояла в том, чтобы обобщить идеи из некоторых других ответов в одно решение, которое могло бы работать для строк, содержащих больше, чем просто слова регулярных выражений (то есть внесение в черный список явного поднабора символов пунктуации против символов слов из белого списка).
Обратите внимание, что при любом подходе можно также рассмотреть возможность использования string.punctuation
вместо определенного вручную списка.
Вариант 1 - re.sub
Я был удивлен, что пока не получил ответа, использует re.sub (...) . Я считаю это простым и естественным подходом к этой проблеме.
import re
my_str = "Hey, you - what are you doing here!?"
words = re.split(r'\s+', re.sub(r'[,\-!?]', ' ', my_str).strip())
В этом решении я вложил вызов re.sub(...)
внутрь re.split(...)
- но если критична производительность, компиляция регулярного выражения извне может быть полезной - для моего случая использования разница не была значительной, поэтому я предпочитаю простоту и удобочитаемость.
Вариант 2 - str.replace
Это еще несколько строк, но оно имеет преимущество, заключающееся в возможности расширения без необходимости проверять необходимость экранирования определенного символа в регулярном выражении.
my_str = "Hey, you - what are you doing here!?"
replacements = (',', '-', '!', '?')
for r in replacements:
my_str = my_str.replace(r, ' ')
words = my_str.split()
Было бы неплохо иметь возможность вместо этого сопоставить str.replace со строкой, но я не думаю, что это можно сделать с неизменяемыми строками, и хотя сопоставление со списком символов будет работать, выполнение каждой замены для каждого символа звучит чрезмерно. (Изменить: см. Следующий вариант для функционального примера.)
Вариант 3 - functools.reduce
(В Python 2 reduce
доступен в глобальном пространстве имен без импорта из functools.)
import functools
my_str = "Hey, you - what are you doing here!?"
replacements = (',', '-', '!', '?')
my_str = functools.reduce(lambda s, sep: s.replace(sep, ' '), replacements, my_str)
words = my_str.split()