8

Лучший способ удалить знаки препинания из строки

18

Кажется, что существует более простой способ, чем:

import string
s = "string. With. Punctuation?" # Пример строки
out = s.translate(string.maketrans("",""), string.punctuation)

Есть ли более простой способ решить эту задачу?

5 ответ(ов)

12

С точки зрения производительности, вы не превзойдете следующий код:

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 показывает наилучшее время выполнения, и его стоит использовать, если вам важна производительность.

2

Регулярные выражения достаточно просты, если вы их знаете.

Ваш код на Python использует модуль re для удаления знаков препинания из строки. Конкретно, он заменяет все символы, которые не являются буквенно-цифровыми (\w) или пробелами (\s), на пустую строку.

Вот как работает ваш код:

import re
s = "string. With. Punctuation?"
s = re.sub(r'[^\w\s]', '', s)

Здесь re.sub() принимает три аргумента:

  1. Паттерн регулярного выражения r'[^\w\s]', который обозначает "всё, что не является буквой, цифрой или пробелом".
  2. Замену, в данном случае пустую строку '', что означает удаление найденных символов.
  3. Исходную строку s.

В результате в переменной s останется строка без знаков препинания: "string With Punctuation".

0

Для удобства использования я обобщил способ удаления знаков препинания из строки как для 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)                                # Результат: строка без знаков препинания
0

Код, который вы привели, использует метод 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, удаляя все указанные знаки.

0

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')

Это также удалит такие символы, как ~*+§$, которые могут считаться "знаками препинания" в зависимости от точки зрения.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь