2009-05-30 4 views
5

Mam bazę danych pełną nazwach takich jak:Python String Cleanup + manipulacja (znaki diakrytyczne)

John Smith 
Scott J. Holmes 
Dr. Kaplan 
Ray's Dog 
Levi's 
Adrian O'Brien 
Perry Sean Smyre 
Carie Burchfield-Thompson 
Björn Árnason 

Istnieje kilka zagranicznych nazwy z akcentami w nich, które muszą być przekształcone w ciągi ze znaków spoza akcentowane .

Chciałbym przekonwertować pełne nazwy (po usunięciu znaków jak "'", "-") w celu logowania użytkownika, takich jak:

john.smith 
scott.j.holmes 
dr.kaplan 
rays.dog 
levis 
adrian.obrien 
perry.sean.smyre 
carie.burchfieldthompson 
bjorn.arnason 

Do tej pory mam:

Fullname.strip() # get rid of leading/trailing white space 
Fullname.lower() # make everything lower case 


... # after bad chars converted/removed 
Fullname.replace(' ', '.') # replace spaces with periods 
+1

To jest zło ​​i zło **, i ogólnie obraźliwe, aby okaleczyć wszystkie takie postacie. Nie możesz nawet poprawnie pisać po angielsku, jeśli to zrobisz. ASCII nie żyje! – tchrist

Odpowiedz

12

Spójrz na ten link [redacted]

Oto kod ze strony

def latin1_to_ascii (unicrap): 
    """This replaces UNICODE Latin-1 characters with 
    something equivalent in 7-bit ASCII. All characters in the standard 
    7-bit ASCII range are preserved. In the 8th bit range all the Latin-1 
    accented letters are stripped of their accents. Most symbol characters 
    are converted to something meaningful. Anything not converted is deleted. 
    """ 
    xlate = { 
     0xc0:'A', 0xc1:'A', 0xc2:'A', 0xc3:'A', 0xc4:'A', 0xc5:'A', 
     0xc6:'Ae', 0xc7:'C', 
     0xc8:'E', 0xc9:'E', 0xca:'E', 0xcb:'E', 
     0xcc:'I', 0xcd:'I', 0xce:'I', 0xcf:'I', 
     0xd0:'Th', 0xd1:'N', 
     0xd2:'O', 0xd3:'O', 0xd4:'O', 0xd5:'O', 0xd6:'O', 0xd8:'O', 
     0xd9:'U', 0xda:'U', 0xdb:'U', 0xdc:'U', 
     0xdd:'Y', 0xde:'th', 0xdf:'ss', 
     0xe0:'a', 0xe1:'a', 0xe2:'a', 0xe3:'a', 0xe4:'a', 0xe5:'a', 
     0xe6:'ae', 0xe7:'c', 
     0xe8:'e', 0xe9:'e', 0xea:'e', 0xeb:'e', 
     0xec:'i', 0xed:'i', 0xee:'i', 0xef:'i', 
     0xf0:'th', 0xf1:'n', 
     0xf2:'o', 0xf3:'o', 0xf4:'o', 0xf5:'o', 0xf6:'o', 0xf8:'o', 
     0xf9:'u', 0xfa:'u', 0xfb:'u', 0xfc:'u', 
     0xfd:'y', 0xfe:'th', 0xff:'y', 
     0xa1:'!', 0xa2:'{cent}', 0xa3:'{pound}', 0xa4:'{currency}', 
     0xa5:'{yen}', 0xa6:'|', 0xa7:'{section}', 0xa8:'{umlaut}', 
     0xa9:'{C}', 0xaa:'{^a}', 0xab:'<<', 0xac:'{not}', 
     0xad:'-', 0xae:'{R}', 0xaf:'_', 0xb0:'{degrees}', 
     0xb1:'{+/-}', 0xb2:'{^2}', 0xb3:'{^3}', 0xb4:"'", 
     0xb5:'{micro}', 0xb6:'{paragraph}', 0xb7:'*', 0xb8:'{cedilla}', 
     0xb9:'{^1}', 0xba:'{^o}', 0xbb:'>>', 
     0xbc:'{1/4}', 0xbd:'{1/2}', 0xbe:'{3/4}', 0xbf:'?', 
     0xd7:'*', 0xf7:'/' 
    } 

    r = '' 
    for i in unicrap: 
     if xlate.has_key(ord(i)): 
      r += xlate[ord(i)] 
     elif ord(i) >= 0x80: 
      pass 
     else: 
      r += i 
    return r 

# This gives an example of how to use latin1_to_ascii(). 
# This creates a string will all the characters in the latin-1 character set 
# then it converts the string to plain 7-bit ASCII. 
if __name__ == '__main__': 
s = unicode('','latin-1') 
for c in range(32,256): 
    if c != 0x7f: 
     s = s + unicode(chr(c),'latin-1') 
print 'INPUT:' 
print s.encode('latin-1') 
print 
print 'OUTPUT:' 
print latin1_to_ascii(s) 
+0

Twój link prowadzi mnie do "Britney Spears nude". – mpen

+2

@Mark - Ha, hura na ciągłość linków internetowych! –

1

chciałbym zrobić coś takiego

# coding=utf-8 

def alnum_dot(name, replace={}): 
    import re 

    for k, v in replace.items(): 
     name = name.replace(k, v) 

    return re.sub("[^a-z.]", "", name.strip().lower()) 

print alnum_dot(u"Frédrik Holmström", { 
    u"ö":"o", 
    " ":"." 
}) 

Drugi argument jest DICT znaków, które mają być zastąpione, wszystko non A-Z i. znaki, które nie zostaną zastąpione, zostaną usunięte

1

Metoda tłumaczenia umożliwia usunięcie znaków. Możesz użyć tego do usunięcia dowolnych znaków.

Fullname.translate(None,"'-\"") 

Jeśli chcesz usunąć całe klasy znaków, możesz użyć modułu re.

re.sub('[^a-z0-9 ]', '', Fullname.strip().lower(),) 
3

Poniższa funkcja jest ogólna:

import unicodedata 

def not_combining(char): 
     return unicodedata.category(char) != 'Mn' 

def strip_accents(text, encoding): 
     unicode_text= unicodedata.normalize('NFD', text.decode(encoding)) 
     return filter(not_combining, unicode_text).encode(encoding) 

# in a cp1252 environment 
>>> print strip_accents("déjà", "cp1252") 
deja 
# in a cp1253 environment 
>>> print strip_accents("καλημέρα", "cp1253") 
καλημερα 

Oczywiście, należy wiedzieć, kodowanie swoich strun.

5

Jeśli nie boisz się instalować modułów innych firm, spójrz na numer python port of the Perl module Text::Unidecode (jest to również on pypi).

Moduł wykonuje tylko translację znaków za pomocą tabeli odnośników. Zerknąłem na kod i wygląda to bardzo prosto. Więc przypuszczam, że działa na prawie każdym systemie operacyjnym i na dowolnej wersji Pythona (crossingfingers). Jest również łatwy do połączenia z aplikacją.

Dzięki temu modułowi nie trzeba ręcznie tworzyć tabeli odnośników (= zmniejszone ryzyko, że jest niekompletna).

Zaletą tego modułu w porównaniu z techniką normalizacji unicode jest to, że: normalizacja Unicode nie zastępuje wszystkich znaków. Dobrym przykładem jest postać typu "æ". Normalizacja Unicode spowoduje wyświetlenie go jako "Letter, smallcase" (Ll). Oznacza to, że za pomocą metody normalize nie otrzymasz ani znaku zastępczego, ani przydatnej wskazówki. Niestety tej postaci nie można przedstawić w ASCII. Więc dostaniesz błędy.

Wymieniona pozycja module wykonuje lepszą pracę. To faktycznie zastąpi "ę" przez "ae". Która jest rzeczywiście przydatna i ma sens.

Najbardziej imponującą rzeczą jaką widziałem jest to, że idzie o wiele dalej.Zastępuje on również znaki w języku japońskim: Kana głównie. Na przykład zastępuje "は" przez "ha". Wszystko jest w porządku. To nie jest głupie, chociaż obecna wersja zastępuje "ち" przez "ti" zamiast "chi". Będziesz więc musiał obchodzić się z nim z troską o bardziej egzotyczne postacie.

Wykorzystanie modułu jest bardzo prosta ::

from unidecode import unidecode 
var_utf8 = "æは".decode("utf8") 
unidecode(var_utf8).encode("ascii") 
>>> "aeha" 

Zauważ, że nie mam nic wspólnego z tym module bezpośrednio. Po prostu uważam, że jest to bardzo przydatne.

Edytuj: Łatka, którą przesłałem, naprawiła błąd dotyczący japońskiej kany. Naprawiłem tylko te, które mogłem od razu zauważyć. Może trochę tęskniłem.

+0

Wczoraj przesłałem łatkę, aby naprawić problemy ze wspomnianymi zamiennikami kana. Zostało już scalone! – exhuma