2012-06-16 12 views
31

Ich habe eine Funktion, die Zeichensetzung aus einer Liste von Strings entfernt:Interpunktion von Unicode formatierte Strings

def strip_punctuation(input): 
    x = 0 
    for word in input: 
     input[x] = re.sub(r'[^A-Za-z0-9 ]', "", input[x]) 
     x += 1 
    return input 

ich meinen Skript vor kurzem Unicode geändert zum Einsatz von Strings, so konnte ich andere nicht-westliche Zeichen verarbeiten. Diese Funktion bricht, wenn sie auf diese Sonderzeichen trifft, und gibt nur leere Unicode-Zeichenfolgen zurück. Wie kann ich Interpunktion von Unicode-formatierten Zeichenfolgen zuverlässig entfernen?

+5

'strip_punctuation()' sollte akzeptieren Strings anstelle von Liste der Zeichenfolgen, dann, wenn Sie es brauchen, könnten Sie 'list_of_strings = map (strip_punctuation, list_of_strings)' – jfs

+0

Das könnte ein besserer Weg tatsächlich sein. Ich mag die Implementierungen Ihrer und F.C. unter Verwendung von Unicode-Kategorien. – acpigeon

Antwort

63

Sie unicode.translate() Methode verwenden:

import unicodedata 
import sys 

tbl = dict.fromkeys(i for i in xrange(sys.maxunicode) 
         if unicodedata.category(unichr(i)).startswith('P')) 
def remove_punctuation(text): 
    return text.translate(tbl) 

Sie auch r'\p{P}' verwenden könnte, die von unterstützt wird regex module:

import regex as re 

def remove_punctuation(text): 
    return re.sub(ur"\p{P}+", "", text) 
+7

+1 für Suggestion Regex - das ist der Weg hier zu gehen. Es ist erwähnenswert, dass es (noch) nicht standard ist und separat installiert werden muss. In py2 benötigen Sie außerdem das Unicode-Muster ("ur" .. "'), um den Unicode-Anpassungsmodus umzuschalten. – georg

+1

@ thg435: Ich habe einen Link zu Regex-Modul hinzugefügt und das Muster Unicode – jfs

+0

@ thg435 Ich stimme zu Regex ist ideal der Weg zu gehen. Leider muss ich meine externen Module auf ein Minimum beschränken, da ich nicht der einzige Benutzer bin.Ich bin mit der früheren Lösung gegangen, die langsam ist, aber es funktioniert. Danke an alle. – acpigeon

8

Sie können die Zeichenfolge mithilfe der -Funktion mithilfe der unicodedata-Funktion durchlaufen, um festzustellen, ob das Zeichen Interpunktion ist.

Für mögliche Ausgänge von category finden unicode.org des doc auf General Category Values

import unicodedata.category as cat 
def strip_punctuation(word): 
    return "".join(char for char in word if cat(char).startswith('P')) 
filtered = [strip_punctuation(word) for word in input] 

Darüber hinaus stellen Sie sicher, dass Sie richtig Kodierungen und Arten der Handhabung. Diese Präsentation ist ein guter Anfang: http://bit.ly/unipain

+0

+1 für Unipain-Link. Ich versuche, dies zu implementieren, aber ich bekomme "IndexError: Liste Zuordnungsindex außerhalb des Bereichs" auf der Zeile Ergebnis [i]. Ich werde weiter herumspielen. – acpigeon

+1

@acpigeon: Aus irgendeinem Grund dachte ich, Sie könnten Listen auf spärliche Weise zuweisen, ohne sie vorher zu füllen. Bearbeitet mit einem besseren Ansatz. – Daenyth

+1

Es gibt einen kleinen aber wichtigen Fehler in dieser Antwort: strip_punctuation macht tatsächlich das Gegenteil von dem, was Sie beabsichtigen, und wird * nur * die Interpunktion zurückgeben, weil Sie ein "nicht" in Ihrem Verständnis vergessen haben. Ich würde die Antwort bearbeiten, um es zu beheben, außer "Änderungen müssen mindestens 6 Zeichen sein." – Edward

7

Etwas kürzere Version basiert auf Daenyth answer

import unicodedata 

def strip_punctuation(text): 
    """ 
    >>> strip_punctuation(u'something') 
    u'something' 

    >>> strip_punctuation(u'something.,:else really') 
    u'somethingelse really' 
    """ 
    punctutation_cats = set(['Pc', 'Pd', 'Ps', 'Pe', 'Pi', 'Pf', 'Po']) 
    return ''.join(x for x in text 
        if unicodedata.category(x) not in punctutation_cats) 

input_data = [u'somehting', u'something, else', u'nothing.'] 
without_punctuation = map(strip_punctuation, input_data) 
+0

OP sagte 'input_data' ist eine Liste von Strings, nicht nur eine Zeichenfolge. (Natürlich können Sie einfach Ihre Version darüber abbilden) – Daenyth

10

Wenn Sie JF Sebastian-Lösung in Python 3 verwenden mögen:

import unicodedata 
import sys 

tbl = dict.fromkeys(i for i in range(sys.maxunicode) 
         if unicodedata.category(chr(i)).startswith('P')) 
def remove_punctuation(text): 
    return text.translate(tbl) 
0

Eine einfache und besser lesbar Lösung wäre:

import string 
punctuations_to_remove = string.punctuation 

# replace any punctuations here with empty '' if you want to keep any punctuations 
# eg. punctuations_to_remove = punctuations_to_remove.replace(".", "") 

unicode_string_without_punctuations = unicode_string_with_punctuations.translate({ord(char): None for char in punctuations_to_remove}) 

Getestet auf Python 2

Verwandte Themen