Лучший способ удалить знаки препинания из строки
Кажется, что существует более простой способ, чем:
import string
s = "string. With. Punctuation?" # Пример строки
out = s.translate(string.maketrans("",""), string.punctuation)
Есть ли более простой способ решить эту задачу?
5 ответ(ов)
С точки зрения производительности, вы не превзойдете следующий код:
s.translate(None, string.punctuation)
Для более поздних версий Python используйте следующий код:
s.translate(str.maketrans('', '', string.punctuation))
Этот подход выполняет операции со строками на C с использованием таблицы соответствий, и его производительность будет выше, чем у большинства чисто питоновских решений. Если вам не важна скорость, есть еще один вариант:
exclude = set(string.punctuation)
s = ''.join(ch for ch in s if ch not in exclude)
Этот вариант быстрее, чем последовательный замен функций s.replace
для каждого символа, но он все равно не будет таким эффективным, как подходы на основе регулярных выражений или string.translate
, как можно увидеть из нижеприведенных замеров. В подобных задачах лучше всего работать на низком уровне.
Код для замеров времени:
import re, string, timeit
s = "string. With. Punctuation"
exclude = set(string.punctuation)
table = string.maketrans("", "")
regex = re.compile('[%s]' % re.escape(string.punctuation))
def test_set(s):
return ''.join(ch for ch in s if ch not in exclude)
def test_re(s): # Исправленный вариант из решения Винко.
return regex.sub('', s)
def test_trans(s):
return s.translate(table, string.punctuation)
def test_repl(s): # Вариант из решения S.Lott.
for c in string.punctuation:
s = s.replace(c, "")
return s
print("sets :", timeit.Timer('f(s)', 'from __main__ import s,test_set as f').timeit(1000000))
print("regex :", timeit.Timer('f(s)', 'from __main__ import s,test_re as f').timeit(1000000))
print("translate :", timeit.Timer('f(s)', 'from __main__ import s,test_trans as f').timeit(1000000))
print("replace :", timeit.Timer('f(s)', 'from __main__ import s,test_repl as f').timeit(1000000))
Это дает следующие результаты:
sets : 19.8566138744
regex : 6.86155414581
translate : 2.12455511093
replace : 28.4436721802
Как видно из этих замеров, translate
показывает наилучшее время выполнения, и его стоит использовать, если вам важна производительность.
Регулярные выражения достаточно просты, если вы их знаете.
Ваш код на Python использует модуль re
для удаления знаков препинания из строки. Конкретно, он заменяет все символы, которые не являются буквенно-цифровыми (\w
) или пробелами (\s
), на пустую строку.
Вот как работает ваш код:
import re
s = "string. With. Punctuation?"
s = re.sub(r'[^\w\s]', '', s)
Здесь re.sub()
принимает три аргумента:
- Паттерн регулярного выражения
r'[^\w\s]'
, который обозначает "всё, что не является буквой, цифрой или пробелом". - Замену, в данном случае пустую строку
''
, что означает удаление найденных символов. - Исходную строку
s
.
В результате в переменной s
останется строка без знаков препинания: "string With Punctuation"
.
Для удобства использования я обобщил способ удаления знаков препинания из строки как для Python 2, так и для Python 3. Пожалуйста, смотрите другие ответы для более подробного описания.
Python 2
import string
s = "строка. С знаками. Пункуация?"
table = string.maketrans("", "")
new_s = s.translate(table, string.punctuation) # Результат: строка без знаков препинания
Python 3
import string
s = "строка. С знаками. Пункуация?"
table = str.maketrans(dict.fromkeys(string.punctuation)) # ИЛИ {key: None for key in string.punctuation}
new_s = s.translate(table) # Результат: строка без знаков препинания
Код, который вы привели, использует метод translate
для удаления всех знаков препинания из строки myString
. Однако в Python 3 этот подход не будет работать, так как None
и string.punctuation
больше не поддерживаются в методе translate
.
Для удаления знаков препинания в Python 3 вы можете использовать str.translate
вместе с str.maketrans
. Вот как это можно сделать:
import string
# Исходная строка
myString = "Привет, мир! Это пример строки с знаками препинания."
# Удаление знаков препинания
myString = myString.translate(str.maketrans('', '', string.punctuation))
print(myString)
В этом коде str.maketrans('', '', string.punctuation)
создает таблицу перевода, которая удаляет все знаки препинания, определенные в string.punctuation
. После этого метод translate
применяет эту таблицу к строке myString
, удаляя все указанные знаки.
string.punctuation
работает только с ASCII! Более корректный (но и более медленный) способ — использовать модуль unicodedata
:
# -*- coding: utf-8 -*-
from unicodedata import category
s = u'String — with - «punctation »...'
s = ''.join(ch for ch in s if category(ch)[0] != 'P')
print 'stripped', s
Вы можете обобщить это и удалить другие типы символов:
''.join(ch for ch in s if category(ch)[0] not in 'SP')
Это также удалит такие символы, как ~*+§$
, которые могут считаться "знаками препинания" в зависимости от точки зрения.
Есть ли в Python метод подстроки 'contains' для строк?
Объединение двух столбцов текста в DataFrame pandas
Вывод строки в текстовый файл
Преобразование всех строк в списке в целые числа
Как извлечь числа из строки в Python?