Rimozione di un elenco di caratteri nella stringa


217

Voglio rimuovere i caratteri in una stringa in Python:

string.replace(',', '').replace("!", '').replace(":", '').replace(";", '')...

Ma ho molti personaggi che devo rimuovere. Ho pensato a un elenco

list = [',', '!', '.', ';'...]

Ma come posso usare il listper sostituire i caratteri nel string?


6
Vedi stackoverflow.com/questions/1919096/… per varie soluzioni e un bel confronto.
Martijn de Milliano,

È un peccato che Python (che si dice venga fornito con le batterie incluse) non gestisca questo caso d'uso fuori dalla scatola. La funzione str_replace di PHP lo fa - puoi passare un array come primo argomento e una stringa come secondo ( php.net/manual/pl/function.str-replace.php ).
JustAC0der

Risposte:


265

Se stai usando python2 e i tuoi input sono stringhe (non unicodes), il metodo assolutamente migliore è str.translate:

>>> chars_to_remove = ['.', '!', '?']
>>> subj = 'A.B!C?'
>>> subj.translate(None, ''.join(chars_to_remove))
'ABC'

Altrimenti, ci sono le seguenti opzioni da considerare:

A. Iterare il carattere soggetto per carattere, omettere i caratteri indesiderati e joinl'elenco risultante:

>>> sc = set(chars_to_remove)
>>> ''.join([c for c in subj if c not in sc])
'ABC'

(Nota che la versione del generatore ''.join(c for c ...)sarà meno efficiente).

B. Crea un'espressione regolare al volo e re.subcon una stringa vuota:

>>> import re
>>> rx = '[' + re.escape(''.join(chars_to_remove)) + ']'
>>> re.sub(rx, '', subj)
'ABC'

( re.escapeassicura che ai personaggi piaccia ^o ]non interrompa l'espressione regolare).

C. Usa la variante di mappatura ditranslate :

>>> chars_to_remove = [u'δ', u'Γ', u'ж']
>>> subj = u'AжBδCΓ'
>>> dd = {ord(c):None for c in chars_to_remove}
>>> subj.translate(dd)
u'ABC'

Codice di prova completo e tempistiche:

#coding=utf8

import re

def remove_chars_iter(subj, chars):
    sc = set(chars)
    return ''.join([c for c in subj if c not in sc])

def remove_chars_re(subj, chars):
    return re.sub('[' + re.escape(''.join(chars)) + ']', '', subj)

def remove_chars_re_unicode(subj, chars):
    return re.sub(u'(?u)[' + re.escape(''.join(chars)) + ']', '', subj)

def remove_chars_translate_bytes(subj, chars):
    return subj.translate(None, ''.join(chars))

def remove_chars_translate_unicode(subj, chars):
    d = {ord(c):None for c in chars}
    return subj.translate(d)

import timeit, sys

def profile(f):
    assert f(subj, chars_to_remove) == test
    t = timeit.timeit(lambda: f(subj, chars_to_remove), number=1000)
    print ('{0:.3f} {1}'.format(t, f.__name__))

print (sys.version)
PYTHON2 = sys.version_info[0] == 2

print ('\n"plain" string:\n')

chars_to_remove = ['.', '!', '?']
subj = 'A.B!C?' * 1000
test = 'ABC' * 1000

profile(remove_chars_iter)
profile(remove_chars_re)

if PYTHON2:
    profile(remove_chars_translate_bytes)
else:
    profile(remove_chars_translate_unicode)

print ('\nunicode string:\n')

if PYTHON2:
    chars_to_remove = [u'δ', u'Γ', u'ж']
    subj = u'AжBδCΓ'
else:
    chars_to_remove = ['δ', 'Γ', 'ж']
    subj = 'AжBδCΓ'

subj = subj * 1000
test = 'ABC' * 1000

profile(remove_chars_iter)

if PYTHON2:
    profile(remove_chars_re_unicode)
else:
    profile(remove_chars_re)

profile(remove_chars_translate_unicode)

risultati:

2.7.5 (default, Mar  9 2014, 22:15:05) 
[GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.0.68)]

"plain" string:

0.637 remove_chars_iter
0.649 remove_chars_re
0.010 remove_chars_translate_bytes

unicode string:

0.866 remove_chars_iter
0.680 remove_chars_re_unicode
1.373 remove_chars_translate_unicode

---

3.4.2 (v3.4.2:ab2c023a9432, Oct  5 2014, 20:42:22) 
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)]

"plain" string:

0.512 remove_chars_iter
0.574 remove_chars_re
0.765 remove_chars_translate_unicode

unicode string:

0.817 remove_chars_iter
0.686 remove_chars_re
0.876 remove_chars_translate_unicode

(Come nota a margine, il dato remove_chars_translate_bytespotrebbe darci un indizio sul perché l'industria è stata riluttante ad adottare Unicode per così tanto tempo).


1
Il secondo metodo genera un errore TypeError: translate() takes exactly one argument (2 given). Apparentemente ci vuole argomento come argomento.
antonavy,

@antonavy - la seconda soluzione funziona - ma solo la stringa non è unicode (per cui è necessaria una diversa translate ())
FuzzyAmi

112

Puoi usare str.translate():

s.translate(None, ",!.;")

Esempio:

>>> s = "asjo,fdjk;djaso,oio!kod.kjods;dkps"
>>> s.translate(None, ",!.;")
'asjofdjkdjasooiokodkjodsdkps'

19
@ thg435: nessuno lo ha chiesto, ma comunque:s.translate(dict.fromkeys(map(ord, u",!.;")))
Sven Marnach

2
Questa (e di PraveenGollakota's) risposta simultanea è esattamente ciò che @Laura ha chiesto e dovrebbe essere la risposta preferita (s).
Piani cottura

7
perché python3: TypeError: translate () accetta esattamente un argomento (2 dato)
Gank

2
@Gank: il unicode.translate()metodo ha parametri diversi rispetto al str.translate()metodo. Utilizzare la variante nel commento sopra per gli oggetti Unicode.
Sven Marnach,

@SvenMarnach cos'è la mappa (ord, u ",!.;"))? e stai per Unicode?
Jun711,


16
''.join(c for c in myString if not c in badTokens)

Utile in casi simili non basati su caratteri e stringhe +1
Lupo

12

Se stai usando python3 e stai cercando la translatesoluzione, la funzione è stata modificata e ora accetta 1 parametro invece di 2.

Quel parametro è una tabella (può essere un dizionario) in cui ogni chiave è l'ordinale Unicode (int) del carattere da trovare e il valore è la sostituzione (può essere un ordinale Unicode o una stringa su cui mappare la chiave).

Ecco un esempio di utilizzo:

>>> list = [',', '!', '.', ';']
>>> s = "This is, my! str,ing."
>>> s.translate({ord(x): '' for x in list})
'This is my string'

8

Un altro approccio che utilizza regex:

''.join(re.split(r'[.;!?,]', s))

7

Perché non un semplice ciclo?

for i in replace_list:
    string = string.replace(i, '')

Inoltre, evita la 'lista' degli elenchi di nomi. Sostituisce la funzione integrata list.


6

potresti usare qualcosa del genere

def replace_all(text, dic):
  for i, j in dic.iteritems():
    text = text.replace(i, j)
  return text

Questo codice non è il mio e viene da qui è un ottimo articolo e ci spiega in profondità facendo questo



3

Forse un modo più moderno e funzionale per ottenere ciò che desideri:

>>> subj = 'A.B!C?'
>>> list = set([',', '!', '.', ';', '?'])
>>> filter(lambda x: x not in list, subj)
'ABC'

tieni presente che per questo scopo particolare è piuttosto eccessivo, ma una volta che hai bisogno di condizioni più complesse, il filtro è utile


Si noti inoltre che ciò può essere fatto altrettanto facilmente con la comprensione delle liste, che secondo me è molto più pitonica.
rivolta il

3

modo semplice,

import re
str = 'this is string !    >><< (foo---> bar) @-tuna-#   sandwich-%-is-$-* good'

// condense multiple empty spaces into 1
str = ' '.join(str.split()

// replace empty space with dash
str = str.replace(" ","-")

// take out any char that matches regex
str = re.sub('[!@#$%^&*()_+<>]', '', str)

produzione:

this-is-string--foo----bar--tuna---sandwich--is---good


1

Che ne dici di questo - una fodera.

reduce(lambda x,y : x.replace(y,"") ,[',', '!', '.', ';'],";Test , ,  !Stri!ng ..")

1

penso che questo sia abbastanza semplice e lo farà!

list = [",",",","!",";",":"] #the list goes on.....

theString = "dlkaj;lkdjf'adklfaj;lsd'fa'dfj;alkdjf" #is an example string;
newString="" #the unwanted character free string
for i in range(len(TheString)):
    if theString[i] in list:
        newString += "" #concatenate an empty string.
    else:
        newString += theString[i]

questo è un modo per farlo. Ma se sei stanco di tenere un elenco di caratteri che desideri rimuovere, puoi effettivamente farlo utilizzando il numero d'ordine delle stringhe in cui esegui l'iterazione. il numero dell'ordine è il valore ASCII di quel personaggio. il numero ascii per 0 come carattere è 48 e il numero ascii per la minuscola z è 122 quindi:

theString = "lkdsjf;alkd8a'asdjf;lkaheoialkdjf;ad"
newString = ""
for i in range(len(theString)):
     if ord(theString[i]) < 48 or ord(theString[i]) > 122: #ord() => ascii num.
         newString += ""
     else:
        newString += theString[i]

0

In questi giorni mi sto immergendo nello schema, e ora penso di essere bravo a ricorrere e valutare. HAHAHA. Condividi solo alcuni nuovi modi:

prima di tutto, valutalo

print eval('string%s' % (''.join(['.replace("%s","")'%i for i in replace_list])))

secondo, reclamalo

def repn(string,replace_list):
    if replace_list==[]:
        return string
    else:
        return repn(string.replace(replace_list.pop(),""),replace_list)

print repn(string,replace_list)

Ehi, non sottovalutare. Voglio solo condividere qualche nuova idea.


0

Sto pensando a una soluzione per questo. Prima di tutto vorrei inserire la stringa come elenco. Quindi vorrei sostituire gli elementi dell'elenco. Quindi, usando il comando join, restituirò l'elenco come stringa. Il codice può essere così:

def the_replacer(text):
    test = []    
    for m in range(len(text)):
        test.append(text[m])
        if test[m]==','\
        or test[m]=='!'\
        or test[m]=='.'\
        or test[m]=='\''\
        or test[m]==';':
    #....
            test[n]=''
    return ''.join(test)

Ciò eliminerebbe qualsiasi cosa dalla stringa. Cosa ne pensi di questo?


0

Ecco un more_itertoolsapproccio:

import more_itertools as mit


s = "A.B!C?D_E@F#"
blacklist = ".!?_@#"

"".join(mit.flatten(mit.split_at(s, pred=lambda x: x in set(blacklist))))
# 'ABCDEF'

Qui dividiamo gli elementi trovati in blacklist, appiattiamo i risultati e uniamo la stringa.


0

Python 3, implementazione della comprensione dell'elenco a riga singola.

from string import ascii_lowercase # 'abcdefghijklmnopqrstuvwxyz'
def remove_chars(input_string, removable):
  return ''.join([_ for _ in input_string if _ not in removable])

print(remove_chars(input_string="Stack Overflow", removable=ascii_lowercase))
>>> 'S O'

0

Rimuovi *%, & @! da sotto la stringa:

s = "this is my string,  and i will * remove * these ** %% "
new_string = s.translate(s.maketrans('','','*%,&@!'))
print(new_string)

# output: this is my string  and i will  remove  these  
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.