836 Stimmen

Beste Methode zum Entfernen von Interpunktionszeichen aus einer Zeichenkette

Es scheint einen einfacheren Weg zu geben als:

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

Gibt es eine?

4 Stimmen

Das scheint mir ziemlich einfach zu sein. Warum wollen Sie es ändern? Wenn Sie es einfacher haben wollen, verpacken Sie einfach, was Sie gerade geschrieben haben, in eine Funktion.

3 Stimmen

Nun, es schien nur ein bisschen hackish zu sein, mit Art von einem Nebeneffekt von str.translate, um die Arbeit zu tun. Ich dachte, es könnte etwas mehr wie str.strip(chars), die auf die gesamte Zeichenfolge anstelle von nur die Grenzen, die ich verpasst hatte gearbeitet werden.

2 Stimmen

Das hängt auch von den Daten ab. Die Verwendung bei Daten, die Servernamen mit Unterstrichen als Teil des Namens enthalten (was an manchen Orten recht häufig vorkommt), könnte schlecht sein. Seien Sie sicher, dass Sie die Daten kennen und wissen, was sie enthalten, oder Sie könnten am Ende mit einer Teilmenge des Problems clbuttic.

1265voto

Brian Punkte 112487

Unter dem Gesichtspunkt der Effizienz werden Sie nicht besser sein als

s.translate(None, string.punctuation)

Für höhere Versionen von Python verwenden Sie den folgenden Code:

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

Es führt rohe String-Operationen in C mit einer Nachschlagetabelle durch - es gibt nicht viel, was das übertrifft, außer Ihren eigenen C-Code zu schreiben.

Wenn die Geschwindigkeit keine Rolle spielt, gibt es eine andere Möglichkeit:

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

Dies ist schneller als s.replace mit jedem Zeichen, aber nicht so gut wie nicht-pure Python-Ansätze wie regexes oder string.translate, wie Sie aus den unten stehenden Zeitangaben sehen können. Bei dieser Art von Problem zahlt es sich aus, es auf einer so niedrigen Ebene wie möglich zu machen.

Zeitlicher Code:

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)

Daraus ergeben sich die folgenden Ergebnisse:

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

35 Stimmen

Vielen Dank für die Timing-Informationen, ich dachte darüber nach, so etwas selbst zu tun, aber Ihre ist besser geschrieben als alles, was ich getan hätte, und jetzt kann ich es als Vorlage für jeden zukünftigen Timing-Code verwenden, den ich schreiben möchte:).

30 Stimmen

Tolle Antwort. Sie können es vereinfachen, indem Sie die Tabelle entfernen. Die Dokumentation sagt: "Setzen Sie das Argument table auf None für Übersetzungen, die nur Zeichen löschen" ( docs.python.org/library/stdtypes.html#str.translate )

1 Stimmen

Verwendung eines Listenverständnisses für die ''.join() würde es ein wenig schneller machen, aber nicht schnell genug, um die regex o translate . Voir Listenverständnis ohne [ ], Python warum das so ist.

202voto

Eratosthenes Punkte 2125

Reguläre Ausdrücke sind einfach genug, wenn man sie kennt.

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

4 Stimmen

@Ausreißer Erläuterung: ersetzt nicht (^)-Wortzeichen oder Leerzeichen durch die leere Zeichenkette. Seien Sie jedoch vorsichtig, die \w passt z.B. auch auf Unterstriche.

6 Stimmen

@SIslam Ich denke, es wird mit Unicode funktionieren, wenn das Unicode-Flag gesetzt ist, d.h. s = re.sub(r'[^\w\s]','',s, re.UNICODE) . Testen Sie es mit Python 3 auf Linux es funktioniert auch ohne die Flagge mit tamilischen Buchstaben, .

1 Stimmen

@Matthias Ich habe den Code mit Python 3.6.5 auf Mac ausprobiert, die Ausgabe der tamilischen Buchstaben sieht ein bisschen anders aus, die Eingabe wird . Ich habe keine Kenntnisse über Tamil, nicht sicher, ob das zu erwarten ist.

92voto

SparkAndShine Punkte 15557

Der Einfachheit halber fasse ich den Hinweis zum Entfernen von Satzzeichen aus einer Zeichenkette sowohl in Python 2 als auch in Python 3 zusammen. Eine detaillierte Beschreibung finden Sie in anderen Antworten.


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

0 Stimmen

Interessant ist, dass diese Lösung (insbesondere die Option OR {Schlüssel: Keine für...}) die Möglichkeit bietet, zu steuern, was anstelle der Interpunktion eingefügt werden soll, z. B. Leerzeichen (verwenden Sie hierfür Schlüssel: " " anstelle von Schlüssel: Keine).

52voto

pyrou Punkte 545
myString.translate(None, string.punctuation)

4 Stimmen

Ah, ich habe das versucht, aber es funktioniert nicht in allen Fällen. myString.translate(string.maketrans("",""), string.punctuation) funktioniert gut.

12 Stimmen

Beachten Sie, dass für str in Python 3, und unicode in Python 2, die deletechars Argument wird nicht unterstützt.

2 Stimmen

@agf: Sie können immer noch utiliser .translate() Interpunktion auch in Unicode- und py3k-Fällen zu entfernen mit Wörterbuchargument.

35voto

Björn Lindqvist Punkte 17705

string.punctuation ist ASCII nur ! Eine korrektere (aber auch viel langsamere) Methode ist die Verwendung des Unicodedata-Moduls:

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

Sie können verallgemeinern und auch andere Arten von Zeichen ausziehen:

''.join(ch for ch in s if category(ch)[0] not in 'SP')

Es werden auch Zeichen wie ~*+§$ was je nach Sichtweise eine "Interpunktion" sein kann oder auch nicht.

4 Stimmen

1 Stimmen

Leider sind Dinge wie ~ gehören nicht zur Kategorie der Zeichensetzung. Sie müssen auch für die Kategorie "Symbole" testen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X