La mejor manera de quitar la puntuación de una cadena en Python

Parece que debería haber una manera más simple que:

import string s = "string. With. Punctuation?" # Sample string out = s.translate(string.maketrans("",""), string.punctuation) 

¿Esta ahí?

Desde una perspectiva de eficiencia, no vas a vencer

 s.translate(None, string.punctuation) 

Para las versiones superiores de Python use el siguiente código:

 s.translate(str.maketrans('', '', string.punctuation)) 

Está realizando operaciones de cadena sin formato en C con una tabla de búsqueda; no hay mucho que pueda superar eso, pero escribir su propio código C.

Si la velocidad no es una preocupación, otra opción es:

 exclude = set(string.punctuation) s = ''.join(ch for ch in s if ch not in exclude) 

Esto es más rápido que en cada caso con cada carácter, pero no funcionará tan bien como los enfoques de Python no puros como regexes o string.translate, como puede ver en los horarios a continuación. Para este tipo de problema, hacerlo en el nivel más bajo posible da sus frutos.

Código de tiempo:

 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) 

Esto da los siguientes resultados:

 sets : 19.8566138744 regex : 6.86155414581 translate : 2.12455511093 replace : 28.4436721802 

Las expresiones regulares son bastante simples, si las conoces.

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

En el código anterior, estamos sustituyendo (re.sub) todos NON [caracteres alfanuméricos (\ w) y espacios (\ s)] con una cadena vacía.
Por lo tanto y? la puntuación no estará presente en la variable ‘s’ después de ejecutar la variable s a través de expresiones regulares.

Para la conveniencia de su uso, resumo la nota de puntuación de una cadena tanto en Python 2 como en Python 3. Consulte otras respuestas para obtener una descripción detallada.


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({key: None for key in string.punctuation}) new_s = s.translate(table) # Output: string without punctuation 
 myString.translate(None, string.punctuation) 

Usualmente uso algo como esto:

 >>> s = "string. With. Punctuation?" # Sample string >>> import string >>> for c in string.punctuation: ... s= s.replace(c,"") ... >>> s 'string With Punctuation' 

string.punctuation es ASCII solamente ! Una forma más correcta (pero también mucho más lenta) es utilizar el módulo 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 

No es necesariamente más simple, sino de una manera diferente, si está más familiarizado con la familia.

 import re, string s = "string. With. Punctuation?" # Sample string out = re.sub('[%s]' % re.escape(string.punctuation), '', s) 

Para los valores de Python 3 str o Python 2 unicode , str.translate() solo toma un diccionario; Los puntos de código (enteros) se buscan en esa asignación y todo lo que se asigne a None se elimina.

Para quitar la puntuación (¿algunos?) Entonces, use:

 import string remove_punct_map = dict.fromkeys(map(ord, string.punctuation)) s.translate(remove_punct_map) 

El método de clase dict.fromkeys() hace que sea trivial crear el mapeo, estableciendo todos los valores en None función de la secuencia de teclas.

Para eliminar toda puntuación, no solo la puntuación ASCII, su tabla debe ser un poco más grande; Vea la respuesta de JF Sebastian (versión 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')) 

string.punctuation pierde string.punctuation signos de puntuación que se usan comúnmente en el mundo real. ¿Qué tal una solución que funcione para la puntuación no 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() 

Personalmente, creo que esta es la mejor manera de eliminar la puntuación de una cadena en Python porque:

  • Se elimina toda la puntuación de Unicode.
  • Es fácilmente modificable, por ejemplo, puede eliminar la \{S} si desea eliminar la puntuación, pero mantenga símbolos como $ .
  • Puede ser realmente específico sobre lo que desea conservar y lo que desea eliminar, por ejemplo, \{Pd} solo eliminará los guiones.
  • Este regex también normaliza los espacios en blanco. Asigna tabs, retornos de carro y otras rarezas a espacios agradables y únicos.

Esto utiliza las propiedades de los caracteres Unicode, sobre las que puedes leer más en Wikipedia .

Esta podría no ser la mejor solución, sin embargo, así es como lo hice.

 import string f = lambda x: ''.join([i for i in x if i not in string.punctuation]) 

Aquí hay una función que escribí. No es muy eficiente, pero es simple y puede agregar o eliminar cualquier puntuación que desee:

 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 

Aquí hay una sola línea para 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})) 

No he visto esta respuesta todavía. Sólo tiene que utilizar un regex; elimina todos los caracteres, además de los caracteres de palabras ( \w ) y números ( \d ), seguidos de un carácter de espacio en blanco ( \s ):

 import re s = "string. With. Punctuation?" # Sample string out = re.sub(ur'[^\w\d\s]+', '', s) 

Aquí hay una solución sin expresiones regulares.

 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 
  • Reemplaza las puntuaciones con espacios.
  • Reemplaza múltiples espacios entre palabras con un solo espacio
  • Retire los espacios finales, si hay alguno con la tira ()

Solo como una actualización, reescribí el ejemplo @Brian en Python 3 e hice cambios para mover el paso de comstackción de expresiones regulares dentro de la función. Mi pensamiento aquí fue progtwigr cada paso necesario para que la función funcione. Tal vez esté utilizando computación distribuida y no pueda compartir objetos de re.compile regulares entre sus trabajadores y necesita tener re.compile paso de re.compile en cada trabajador. Además, tenía curiosidad por cronometrar dos implementaciones diferentes de maketrans para Python 3

 table = str.maketrans({key: None for key in string.punctuation}) 

vs

 table = str.maketrans('', '', string.punctuation) 

Además, agregué otro método para usar set, donde aprovecho la función de intersección para reducir el número de iteraciones.

Este es el código completo:

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

Estos son mis resultados:

 sets : 3.1830138750374317 sets2 : 2.189873124472797 regex : 7.142953420989215 translate : 4.243278483860195 translate2 : 2.427158243022859 replace : 4.579746678471565 
 >>> s = "string. With. Punctuation?" >>> s = re.sub(r'[^\w\s]','',s) >>> re.split(r'\s*', s) ['string', 'With', 'Punctuation'] 
 import re s = "string. With. Punctuation?" # Sample string out = re.sub(r'[^a-zA-Z0-9\s]', '', s) 

Un one-liner podría ser útil en casos no muy estrictos:

 ''.join([c for c in s if c.isalnum() or c.isspace()]) 

Busque y reemplace usando las funciones regex, como se ve aquí. . Si tiene que realizar la operación repetidamente, puede mantener una copia comstackda del patrón de expresiones regulares (su puntuación), lo que acelerará un poco las cosas.

 #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 ("____________") 

Elimina las palabras de parada del archivo de texto usando 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') 

Así es como cambiamos nuestros documentos a mayúsculas o minúsculas.

 print('@@@@This is lower case@@@@') with open('students.txt','r')as myFile: str1=myFile.read() str1.lower() print(str1.lower()) print('*****This is upper case****') with open('students.txt','r')as myFile: str1=myFile.read() str1.upper() print(str1.upper()) 

Me gusta usar una función como esta:

 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