Entfernen einer Liste von Zeichen in einer Zeichenfolge

217

Ich möchte Zeichen in einer Zeichenfolge in Python entfernen:

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

Aber ich habe viele Zeichen, die ich entfernen muss. Ich dachte über eine Liste nach

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

Aber wie kann ich das verwenden list, um die Zeichen in der zu ersetzen string?

Laura
quelle
6
Unter stackoverflow.com/questions/1919096/… finden Sie verschiedene Lösungen und einen schönen Vergleich.
Martijn de Milliano
Es ist schade, dass Python (das angeblich mit Batterien geliefert wird) diesen Anwendungsfall nicht sofort behandelt. Die PHP-Funktion str_replace erledigt dies - Sie können ein Array als erstes Argument und einen String als zweites übergeben ( php.net/manual/pl/function.str-replace.php ).
JustAC0der

Antworten:

264

Wenn Sie python2 verwenden und Ihre Eingaben Zeichenfolgen (keine Unicodes) sind, ist die absolut beste Methode str.translate:

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

Andernfalls sind folgende Optionen zu berücksichtigen:

A. Iterieren Sie den Betreff char by char, lassen Sie unerwünschte Zeichen und joindie resultierende Liste weg :

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

(Beachten Sie, dass die Generatorversion ''.join(c for c ...)weniger effizient ist).

B. Erstellen Sie einen regulären Ausdruck im laufenden Betrieb und re.submit einer leeren Zeichenfolge:

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

( re.escapestellt sicher, dass Zeichen den regulären Ausdruck mögen ^oder ]nicht brechen).

C. Verwenden Sie die Mapping-Variante vontranslate :

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

Vollständiger Testcode und Timings:

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

Ergebnisse:

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

(Als Randnotiz remove_chars_translate_byteskönnte die Zahl für uns einen Hinweis geben, warum die Branche Unicode so lange nicht einführen wollte).

georg
quelle
1
Die zweite Methode löst einen Fehler aus TypeError: translate() takes exactly one argument (2 given). Anscheinend braucht es Diktat als Argument.
Antonavy
@antonavy - die 2. Lösung funktioniert - aber nur der String ist kein Unicode (für den eine andere translate () benötigt wird)
FuzzyAmi
112

Sie können verwenden str.translate():

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

Beispiel:

>>> s = "asjo,fdjk;djaso,oio!kod.kjods;dkps"
>>> s.translate(None, ",!.;")
'asjofdjkdjasooiokodkjodsdkps'
Sven Marnach
quelle
19
@ thg435: Niemand hat danach gefragt, aber trotzdem:s.translate(dict.fromkeys(map(ord, u",!.;")))
Sven Marnach
2
Diese (und @ PraveenGollakotas) gleichzeitige Antwort ist genau das, wonach @Laura gefragt hat und sollte die bevorzugte (n) Antwort (en) sein.
Kochfelder
7
warum python3: TypeError: translate () nimmt genau ein Argument (2 angegeben)
Gank
2
@Gank: Die unicode.translate()Methode hat andere Parameter als die str.translate()Methode. Verwenden Sie die Variante im obigen Kommentar für Unicode-Objekte.
Sven Marnach
@SvenMarnach was ist map (ord, u ",!.;"))? und stehst du für Unicode?
Jun711
16
''.join(c for c in myString if not c in badTokens)
Ninjagecko
quelle
Nützlich in ähnlichen Fällen, die nicht auf Zeichen und Zeichenfolgen basieren +1
Wolf
12

Wenn Sie python3 verwenden und nach einer translateLösung suchen, wurde die Funktion geändert und verwendet jetzt 1 Parameter anstelle von 2.

Dieser Parameter ist eine Tabelle (kann ein Wörterbuch sein), in der jeder Schlüssel die Unicode-Ordnungszahl (int) des zu suchenden Zeichens und der Wert die Ersetzung ist (kann entweder eine Unicode-Ordnungszahl oder eine Zeichenfolge sein, der der Schlüssel zugeordnet werden soll).

Hier ist ein Anwendungsbeispiel:

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

Ein anderer Ansatz mit Regex:

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

Warum nicht eine einfache Schleife?

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

Vermeiden Sie es auch, Listen als "Liste" zu bezeichnen. Es überschreibt die eingebaute Funktion list.

aIKid
quelle
6

Sie könnten so etwas gebrauchen

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

Dieser Code ist nicht mein eigener und stammt von hier. Er ist ein großartiger Artikel und geht ausführlich darauf ein

krystan Ehre
quelle
3

Ein ebenfalls interessantes Thema zum Entfernen von UTF-8-Akzenten ist die Zeichenfolge, mit der Zeichen in ihre nicht akzentuierten Standardzeichen umgewandelt werden:

Was ist der beste Weg, um Akzente in einer Python-Unicode-Zeichenfolge zu entfernen?

Code-Auszug aus dem Thema:

import unicodedata

def remove_accents(input_str):
    nkfd_form = unicodedata.normalize('NFKD', input_str)
    return u"".join([c for c in nkfd_form if not unicodedata.combining(c)])
Sylvain
quelle
3

Vielleicht ein moderner und funktionaler Weg, um das zu erreichen, was Sie wünschen:

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

Bitte beachten Sie, dass es für diesen speziellen Zweck ein ziemlicher Overkill ist. Wenn Sie jedoch komplexere Bedingungen benötigen, ist der Filter praktisch

Aufruhr
quelle
Beachten Sie auch, dass dies genauso gut mit Listenverständnissen möglich ist, was meiner Meinung nach viel pythonischer ist.
Aufruhr
3

einfacher Weg,

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)

Ausgabe:

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

perfecto25
quelle
1

Wie wäre es damit - ein Einzeiler.

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

Ich denke, das ist einfach genug und wird es tun!

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]

Dies ist eine Möglichkeit, dies zu tun. Wenn Sie es jedoch satt haben, eine Liste der Zeichen zu führen, die Sie entfernen möchten, können Sie dies tatsächlich tun, indem Sie die Bestellnummer der Zeichenfolgen verwenden, die Sie durchlaufen. Die Bestellnummer ist der ASCII-Wert dieses Zeichens. Die ASCII-Zahl für 0 als Zeichen ist 48 und die ASCII-Zahl für Kleinbuchstaben z ist 122, also:

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]
Hiskel Kelemework
quelle
0

In diesen Tagen tauche ich in das Schema ein und jetzt denke ich, dass ich gut darin bin, zu rekursieren und zu bewerten. HAHAHA. Teilen Sie einfach einige neue Wege:

Bewerten Sie es zuerst

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

zweitens, rekursiere es

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)

Hey, stimme nicht ab. Ich möchte nur eine neue Idee teilen.

tcpiper
quelle
0

Ich denke über eine Lösung dafür nach. Zuerst würde ich die Zeichenfolge als Liste eingeben. Dann würde ich die Listenelemente ersetzen. Dann werde ich mit dem Befehl join die Liste als Zeichenfolge zurückgeben. Der Code kann folgendermaßen aussehen:

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)

Dies würde alles aus der Zeichenfolge entfernen. Was denkst du darüber?

Scheich Ahmad Shah
quelle
0

Hier ist ein more_itertoolsAnsatz:

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'

Hier teilen wir die in gefundenen Elemente auf blacklist, reduzieren die Ergebnisse und verbinden die Zeichenfolge.

Pylang
quelle
0

Python 3, Implementierung eines einzeiligen Listenverständnisses.

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'
John Forbes
quelle
0

Entfernen *%,&@! von unten Zeichenfolge:

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  
Biplob Das
quelle