Похоже, должен быть способ попроще, чем:
import string
s = "string. With. Punctuation?" # Sample string
out = s.translate(string.maketrans("",""), string.punctuation)
Здесь?
Что ж, это просто казалось хакерским - использовать побочный эффект str.translate для выполнения работы. Я думал, что может быть что-то вроде str.strip (chars), которое работает со всей строкой, а не только с границами, которые я пропустил.
Зависит и от данных. Использование этого для данных, где есть имена серверов с подчеркиванием как часть имени (довольно часто в некоторых местах), может быть плохим. Просто убедитесь, что вы знаете данные и их содержание, иначе вы можете столкнуться с подмножеством проблемы clbuttic.
Зависит также от того, что вы называете пунктуацией. "The temperature in the O'Reilly & Arbuthnot-Smythe server's main rack is 40.5 degrees." содержит ровно ОДИН знак препинания, второй "."
Я удивлен, что никто не упомянул, что string.punctuation вообще не включает неанглийскую пунктуацию. Я думаю о。 ,!? : × «» 〟и так далее.
Не работает со строкой юникода?
Начиная с python 3.1 (как минимум до 3.8.3) вам понадобится: str.maketrans("","", string.punctuation) на эта документация с изменением задокументировано в 3.1
Большая часть обсуждения здесь - это Python 2, этот вопрос похож, но есть превосходные ответы Python 3.






Не обязательно проще, но по-другому, если вы больше знакомы с семьей re.
import re, string
s = "string. With. Punctuation?" # Sample string
out = re.sub('[%s]' % re.escape(string.punctuation), '', s)
Работает, потому что строка string.punctuation имеет последовательность, -. в правильном, возрастающем, без пробелов, порядке ASCII. Хотя Python имеет это право, когда вы пытаетесь использовать подмножество string.punctuation, это может стать препятствием для показа из-за неожиданности «-».
На самом деле это все еще неправильно. Последовательность «\]» обрабатывается как escape (по совпадению не закрывающая], чтобы избежать другого сбоя), но оставляет \ без экранирования. Вы должны использовать re.escape (string.punctuation), чтобы предотвратить это.
Да, я пропустил его, потому что он работал для примера, чтобы упростить задачу, но вы правы, что его следует включить.
Обычно я использую что-то вроде этого:
>>> s = "string. With. Punctuation?" # Sample string
>>> import string
>>> for c in string.punctuation:
... s= s.replace(c,"")
...
>>> s
'string With Punctuation'
Углифицированный однострочный файл: reduce(lambda s,c: s.replace(c, ''), string.punctuation, s).
отлично, но не устраняет некоторые знаки препинания, такие как длинный дефис
С точки зрения эффективности вы не победите
s.translate(None, string.punctuation)
Для более высоких версий Python используйте следующий код:
s.translate(str.maketrans('', '', string.punctuation))
Он выполняет операции с необработанными строками на C с помощью таблицы поиска - мало что может превзойти это, кроме написания собственного кода C.
Если скорость не вызывает беспокойства, есть еще один вариант:
exclude = set(string.punctuation)
s = ''.join(ch for ch in s if ch not in exclude)
Это быстрее, чем s.replace с каждым символом, но не будет работать так же хорошо, как подходы, не являющиеся чистыми python, такие как регулярные выражения или 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): # From Vinko's solution, with fix.
return regex.sub('', s)
def test_trans(s):
return s.translate(table, string.punctuation)
def test_repl(s): # From S.Lott's solution
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
Спасибо за информацию о времени, я сам думал о том, чтобы сделать что-то подобное, но твое написано лучше, чем все, что я сделал бы, и теперь я могу использовать его в качестве шаблона для любого будущего кода времени, который я хочу написать :).
Отличный ответ. Вы можете упростить его, убрав таблицу. В документах говорится: «установите для аргумента таблицы значение Нет для переводов, которые удаляют только символы» (docs.python.org/library/stdtypes.html#str.translate)
Использование списка для ''.join() сделало бы его немного быстрее, но недостаточно быстро, чтобы превзойти regex или translate. См. понимание списка без [], Python, почему это так.
Также стоит отметить, что translate () ведет себя по-разному для объектов str и unicode, поэтому вы должны быть уверены, что всегда работаете с одним и тем же типом данных, но подход в этом ответе одинаково хорошо работает для обоих, что удобно.
В Python3 следует заменить table = string.maketrans("","") на table = str.maketrans({key: None for key in string.punctuation})?
С какой целью делать set(string.punctuation)? У него есть только уникальные значения.
@mlissner - эффективность. Если это список / строка, вам нужно выполнить линейное сканирование, чтобы узнать, находится ли буква в строке. Однако с набором или словарем он обычно будет быстрее (за исключением действительно маленьких строк), поскольку ему не нужно проверять каждое значение.
@sparkandshine Да, за исключением того, что вам нужно сопоставить порядковые номера каждого ключа символу замены, поэтому в Python 3 это будет s.translate({ord(c): None for c in string.punctuation}).
Чтобы обновить обсуждение, начиная с Python 3.6, regex теперь является наиболее эффективным методом! Это почти в 2 раза быстрее, чем переводчик. Кроме того, наборы и замены уже не так уж и плохи! Оба они улучшены более чем в 4 раза :)
В Python 3 таблицу перевода также можно создать с помощью table = str.maketrans('', '', string.punctuation)docs.python.org/3/library/stdtypes.html#str.maketrans
Большое спасибо за временную сложность каждого подхода.
>>> s.translate (None, string.punctuation) Traceback (последний вызов последним): файл «<stdin>», строка 1, в <module> TypeError: str.translate () принимает ровно один аргумент (задано 2) в python3, я думаю, этот ответ нуждается в обновлении
Спасибо за тонну информации. Полезно
myString.translate(None, string.punctuation)
ах, я пробовал это, но это работает не во всех случаях. myString.translate (string.maketrans ("", ""), string.punctuation) работает нормально.
Обратите внимание, что для str в Python 3 и unicode в Python 2 аргумент deletechars не поддерживается.
@agf: вы все еще можете используйте .translate() для удаления знаков препинания даже в случаях Unicode и py3k, используя аргумент словаря.
myString.translate (string.maketrans ("", ""), string.punctuation) НЕ будет работать со строками Unicode (выяснилось на собственном опыте)
@MarcMaxson: myString.translate(str.maketrans("", "", string.punctuation)) действительно работает для строк Unicode на Python 3. Хотя string.punctuation включает только знаки препинания ascii. Щелкните ссылка в моем предыдущем комментарии. Он показывает, как удалить все знаки препинания (включая Unicode).
TypeError: translate() takes exactly one argument (2 given) :(
@BrianTingle: посмотрите код Python 3 в моем комментарии (он передает один аргумент). Перейдите по ссылке, чтобы увидеть код Python 2, который работает с юникодом. и его адаптация Python 3
Возможно, это не лучшее решение, но я сделал это так.
import string
f = lambda x: ''.join([i for i in x if i not in string.punctuation])
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')
Он также удалит такие символы, как ~*+§$, которые могут быть или не быть «пунктуацией» в зависимости от точки зрения.
Мне нравится использовать такую функцию:
def scrub(abc):
while abc[-1] is in list(string.punctuation):
abc=abc[:-1]
while abc[0] is in list(string.punctuation):
abc=abc[1:]
return abc
Это удаление символов с начала и с конца; используйте для этого abc.strip(string.punctuation). Он не удалит такие символы в центре.
Регулярные выражения достаточно просты, если вы их знаете.
import re
s = "string. With. Punctuation?"
s = re.sub(r'[^\w\s]','',s)
@Outlier Explanation: заменяет символы слова not (^) или пробелы пустой строкой. Однако будьте осторожны, например, \ w слишком часто совпадает с подчеркиванием.
@SIslam Я думаю, он будет работать с юникодом с установленным флагом юникода, то есть s = re.sub(r'[^\w\s]','',s, re.UNICODE). Тестируя его с помощью python 3 в Linux, он работает даже без флага с тамильскими буквами தமிழ்.
@Matthias Я пробовал код с Python 3.6.5 на Mac, вывод тамильских букв выглядит немного иначе, ввод தமிழ் становится தமழ. Я ничего не знаю о тамильском, не уверен, что это ожидается.
@Matthias Он путается с границами слов при работе с UNICODE бенгальским текстом и дает неправильные слова независимо от того, используется флаг UNICODE или нет.
Для значений Python 3 str или Python 2 unicodestr.translate() принимает только словарь; кодовые точки (целые числа) ищутся в этом сопоставлении, и все, что сопоставлено с None, удаляется.
Чтобы удалить (некоторые?) Знаки препинания, используйте:
import string
remove_punct_map = dict.fromkeys(map(ord, string.punctuation))
s.translate(remove_punct_map)
dict.fromkeys() метод класса упрощает создание сопоставления, устанавливая все значения на None на основе последовательности ключей.
Чтобы удалить знаки препинания все, а не только знаки препинания ASCII, ваша таблица должна быть немного больше; см. Ответ Дж. Ф. Себастьяна (версия Python 3):
import unicodedata
import sys
remove_punct_map = dict.fromkeys(i for i in range(sys.maxunicode)
if unicodedata.category(chr(i)).startswith('P'))
Для поддержки Unicode string.punctuation недостаточно. См. мой ответ
@ Дж. Ф. Себастьян: действительно, в моем ответе использовались те же символы, что и в голосе, получившем наибольшее количество голосов. Добавлена версия вашей таблицы для Python 3.
ответ, получивший наибольшее количество голосов, работает только для строк ascii. Ваш ответ явно заявляет о поддержке Unicode.
@ J.F.Sebastian: он работает для строк Unicode. Он удаляет знаки препинания ASCII. Я никогда не утверждал, что он удаляет знаки препинания все. :-) Суть в том, чтобы предоставить правильную технику для объектов unicode по сравнению с объектами Python 2 str.
Вот функция, которую я написал. Это не очень эффективно, но это просто, и вы можете добавлять или удалять любые знаки препинания, которые захотите:
def stripPunc(wordList):
"""Strips punctuation from list of words"""
puncList = [".",";",":","!","?","/","\\",",","#","@","$","&",")","(","\""]
for punc in puncList:
for word in wordList:
wordList=[word.replace(punc,'') for word in wordList]
return wordList
Однострочник может быть полезен в не очень строгих случаях:
''.join([c for c in s if c.isalnum() or c.isspace()])
Вот однострочный текст для Python 3.5:
import string
"l*ots! o(f. p@u)n[c}t]u[a'ti\"on#$^?/".translate(str.maketrans({a:None for a in string.punctuation}))
Для удобства использования я резюмирую примечание о разделении знаков препинания в строке как в Python 2, так и в Python 3. Подробное описание см. В других ответах.
Python 2
import string
s = "string. With. Punctuation?"
table = string.maketrans("","")
new_s = s.translate(table, string.punctuation) # Output: string without punctuation
Python 3
import string
s = "string. With. Punctuation?"
table = str.maketrans(dict.fromkeys(string.punctuation)) # OR {key: None for key in string.punctuation}
new_s = s.translate(table) # Output: string without punctuation
Я еще не видел этого ответа. Просто используйте регулярное выражение; он удаляет все символы, кроме символов слова (\w) и цифровых символов (\d), за которыми следует пробельный символ (\s):
import re
s = "string. With. Punctuation?" # Sample string
out = re.sub(ur'[^\w\d\s]+', '', s)
\d является избыточным, поскольку он является подмножеством \w.
Числовые символы считаются подмножеством символов Word? Я думал, что символ Word - это любой символ, который может составить настоящее слово, например а-я-я?
Да, «слово» в регулярном выражении включает буквы, числа и подчеркивание. См. Описание \w в документации: docs.python.org/3/library/re.html
>>> s = "string. With. Punctuation?"
>>> s = re.sub(r'[^\w\s]','',s)
>>> re.split(r'\s*', s)
['string', 'With', 'Punctuation']
Пожалуйста, отредактируйте с дополнительной информацией. Ответы только на код и "попробуйте это" не приветствуются, потому что они не содержат доступного для поиска контента и не объясняют, почему кто-то должен "попробовать это".
string.punctuation пропускает множество знаков препинания, которые обычно используются в реальном мире. Как насчет решения, которое работает с пунктуацией, отличной от ASCII?
import regex
s = u"string. With. Some・Really Weird、Non?ASCII。 「(Punctuation)」?"
remove = regex.compile(ur'[\p{C}|\p{M}|\p{P}|\p{S}|\p{Z}]+', regex.UNICODE)
remove.sub(u" ", s).strip()
Лично я считаю, что это лучший способ удалить знаки препинания из строки в Python, потому что:
\{S}, если хотите убрать знаки препинания, но оставить символы вроде $.\{Pd} удалит только тире.При этом используются свойства символов Юникода, которые вы можете узнать больше в Википедии.
Эта строчка на самом деле не работает: remove = regex.compile(ur'[\p{C}|\p{M}|\p{P}|\p{S}|\p{Z}]+', regex.UNICODE)
Вот решение без регулярного выражения.
import string
input_text = "!where??and!!or$$then:)"
punctuation_replacer = string.maketrans(string.punctuation, ' '*len(string.punctuation))
print ' '.join(input_text.translate(punctuation_replacer).split()).strip()
Output>> where and or then
#FIRST METHOD
#Storing all punctuations in a variable
punctuation='!?,.:;"\')(_-'
newstring='' #Creating empty string
word=raw_input("Enter string: ")
for i in word:
if (i not in punctuation):
newstring+=i
print "The string without punctuation is",newstring
#SECOND METHOD
word=raw_input("Enter string: ")
punctuation='!?,.:;"\')(_-'
newstring=word.translate(None,punctuation)
print "The string without punctuation is",newstring
#Output for both methods
Enter string: hello! welcome -to_python(programming.language)??,
The string without punctuation is: hello welcome topythonprogramminglanguage
with open('one.txt','r')as myFile:
str1=myFile.read()
print(str1)
punctuation = ['(', ')', '?', ':', ';', ',', '.', '!', '/', '"', "'"]
for i in punctuation:
str1 = str1.replace(i," ")
myList=[]
myList.extend(str1.split(" "))
print (str1)
for i in myList:
print(i,end='\n')
print ("____________")
Удалите стоп-слова из текстового файла с помощью Python
print('====THIS IS HOW TO REMOVE STOP WORS====')
with open('one.txt','r')as myFile:
str1=myFile.read()
stop_words = "not", "is", "it", "By","between","This","By","A","when","And","up","Then","was","by","It","If","can","an","he","This","or","And","a","i","it","am","at","on","in","of","to","is","so","too","my","the","and","but","are","very","here","even","from","them","then","than","this","that","though","be","But","these"
myList=[]
myList.extend(str1.split(" "))
for i in myList:
if i not in stop_words:
print ("____________")
print(i,end='\n')
import re
s = "string. With. Punctuation?" # Sample string
out = re.sub(r'[^a-zA-Z0-9\s]', '', s)
Похоже, это будет работать только для символов ASCII.
В качестве обновления я переписал пример @Brian в Python 3 и внес в него изменения, чтобы переместить этап компиляции регулярного выражения внутри функции. Моя мысль здесь заключалась в том, чтобы рассчитать каждый шаг, необходимый для работы функции. Возможно, вы используете распределенные вычисления и не можете разделять объект регулярного выражения между вашими рабочими, и вам нужно иметь шаг re.compile для каждого рабочего. Кроме того, мне было любопытно примерить две разные реализации maketrans для Python 3.
table = str.maketrans({key: None for key in string.punctuation})
против
table = str.maketrans('', '', string.punctuation)
Кроме того, я добавил еще один метод использования set, в котором я использую функцию пересечения, чтобы уменьшить количество итераций.
Это полный код:
import re, string, timeit
s = "string. With. Punctuation"
def test_set(s):
exclude = set(string.punctuation)
return ''.join(ch for ch in s if ch not in exclude)
def test_set2(s):
_punctuation = set(string.punctuation)
for punct in set(s).intersection(_punctuation):
s = s.replace(punct, ' ')
return ' '.join(s.split())
def test_re(s): # From Vinko's solution, with fix.
regex = re.compile('[%s]' % re.escape(string.punctuation))
return regex.sub('', s)
def test_trans(s):
table = str.maketrans({key: None for key in string.punctuation})
return s.translate(table)
def test_trans2(s):
table = str.maketrans('', '', string.punctuation)
return(s.translate(table))
def test_repl(s): # From S.Lott's solution
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("sets2 :",timeit.Timer('f(s)', 'from __main__ import s,test_set2 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("translate2 :",timeit.Timer('f(s)', 'from __main__ import s,test_trans2 as f').timeit(1000000))
print("replace :",timeit.Timer('f(s)', 'from __main__ import s,test_repl as f').timeit(1000000))
Это мои результаты:
sets : 3.1830138750374317
sets2 : 2.189873124472797
regex : 7.142953420989215
translate : 4.243278483860195
translate2 : 2.427158243022859
replace : 4.579746678471565
Почему никто из вас этим не пользуется?
''.join(filter(str.isalnum, s))
Слишком медленно?
Обратите внимание, что это также удалит пробелы.
Учитывая юникод. Код проверен в python3.
from unicodedata import category
text = 'hi, how are you?'
text_without_punc = ''.join(ch for ch in text if not category(ch).startswith('P'))
Вот еще один простой способ сделать это с помощью RegEx
import re
punct = re.compile(r'(\w+)')
sentence = 'This ! is : a # sample $ sentence.' # Text with punctuation
tokenized = [m.group() for m in punct.finditer(sentence)]
sentence = ' '.join(tokenized)
print(sentence)
'This is a sample sentence'
Попробуйте это :)
regex.sub(r'\p{P}','', s)
Я искал действительно простое решение. вот что у меня получилось:
import re
s = "string. With. Punctuation?"
s = re.sub(r'[\W\s]', ' ', s)
print(s)
'string With Punctuation '
Мне это кажется довольно простым. Почему вы хотите это изменить? Если вы хотите, чтобы было проще, просто оберните то, что вы только что написали, в функцию.