Sto cercando di eliminare la punteggiatura in modo efficiente da una stringa unicode. Con una stringa normale, utilizzando mystring.translate(None, string.punctuation)
è chiaramente il fastest approach. Tuttavia, questo codice si interrompe su una stringa unicode in Python 2.7. Come spiegano i commenti a questo answer, il metodo di traduzione può ancora essere implementato, ma deve essere implementato con un dizionario. Tuttavia, quando utilizzo questo implementation, trovo che le prestazioni di translate si riducano drasticamente. Qui è il mio codice di distribuzione (copiato in primo luogo da questa answer):Il modo più veloce per eliminare la punteggiatura da una stringa unicode in Python
import re, string, timeit
import unicodedata
import sys
#String from this article www.wired.com/design/2013/12/find-the-best-of-reddit-with-this-interactive-map/
s = "For me, Reddit brings to mind Obi Wan’s enduring description of the Mos Eisley cantina: a wretched hive of scum and villainy. But, you know, one you still kinda want to hang out in occasionally. The thing is, though, Reddit isn’t some obscure dive bar in a remote corner of the universe—it’s a huge watering hole at the very center of it. The site had some 400 million unique visitors in 2012. They can’t all be Greedos. So maybe my problem is just that I’ve never been able to find the places where the decent people hang out."
su = u"For me, Reddit brings to mind Obi Wan’s enduring description of the Mos Eisley cantina: a wretched hive of scum and villainy. But, you know, one you still kinda want to hang out in occasionally. The thing is, though, Reddit isn’t some obscure dive bar in a remote corner of the universe—it’s a huge watering hole at the very center of it. The site had some 400 million unique visitors in 2012. They can’t all be Greedos. So maybe my problem is just that I’ve never been able to find the places where the decent people hang out."
exclude = set(string.punctuation)
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(None, string.punctuation)
tbl = dict.fromkeys(i for i in xrange(sys.maxunicode)
if unicodedata.category(unichr(i)).startswith('P'))
def test_trans_unicode(su):
return su.translate(tbl)
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)
print "sets (unicode) :",timeit.Timer('f(su)', 'from __main__ import su,test_set as f').timeit(1000000)
print "regex (unicode) :",timeit.Timer('f(su)', 'from __main__ import su,test_re as f').timeit(1000000)
print "translate (unicode) :",timeit.Timer('f(su)', 'from __main__ import su,test_trans_unicode as f').timeit(1000000)
print "replace (unicode) :",timeit.Timer('f(su)', 'from __main__ import su,test_repl as f').timeit(1000000)
Come i miei risultati mostrano, l'attuazione unicode di tradurre esegue orribilmente:
sets : 38.323941946
regex : 6.7729549408
translate : 1.27428412437
replace : 5.54967689514
sets (unicode) : 43.6268708706
regex (unicode) : 7.32343912125
translate (unicode) : 54.0041439533
replace (unicode) : 17.4450061321
La mia domanda è se c'è un modo più veloce per implementare translate per unicode (o qualsiasi altro metodo) che possa sovraperformare la regex.
dare un'occhiata veloce al codice sorgente C del ' translate' incorporato tra 'stringobject.c' e' unicodeobject.c' sono effettivamente implementati in modo molto diverso. – qwwqwwq
Probabilmente potresti velocizzarlo, sì. Ci sono un sacco di chiamate di funzione che sono principalmente per chiarezza; questi potrebbero essere inline. Il problema principale per l'implementazione è che i char unicode sono più intensi da analizzare e che il numero di possibili sostituzioni è molto più grande (il tuo 'tbl' contiene 585 caratteri) che richiede la strategia della mappa usata in' unicodeobject'. Il metodo regex è troppo lento? – beerbajay
Non stavo nemmeno pensando all'implementazione C, volevo solo dire che esiste il codice Python esistente che può sovraperformare il metodo regex. Il metodo regex andrà bene, è quello che ho implementato per ora, ma è cinque volte più lento e ho un sacco di testo, quindi ho pensato di chiedere. – Michael