Python String Cleanup + Manipulation (Подчеркнутые символы) - PullRequest
5 голосов
/ 30 мая 2009

У меня есть база данных, полная имен, таких как:

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

Есть несколько иностранных имен с акцентами в них, которые необходимо преобразовать в строки с символами без акцента.

Я хотел бы преобразовать полные имена (после удаления таких символов, как "'", "-") в логины пользователя, например:

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

Пока у меня есть:

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

Ответы [ 5 ]

12 голосов
/ 30 мая 2009

Взгляните на эту ссылку [отредактировано]

Вот код со страницы

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)
5 голосов
/ 26 августа 2009

Если вы не боитесь устанавливать сторонние модули, взгляните на порт Python модуля Perl Text::Unidecode (он также на pypi ).

Модуль не более чем использует таблицу поиска для транслитерации символов. Я посмотрел на код, и он выглядит очень просто. Поэтому я полагаю, что он работает практически на любой ОС и на любой версии Python (скрещивание пальцев). Это также легко в комплекте с вашим приложением.

С этим модулем вам не нужно создавать свою справочную таблицу вручную (= снижается риск ее неполного заполнения).

Преимущество этого модуля по сравнению с техникой нормализации Unicode заключается в следующем: нормализация Unicode не заменяет все символы. Хорошим примером является такой персонаж, как «æ». Нормализация Unicode будет выглядеть как «Буква, строчные буквы» (Ll). Это означает, что использование метода normalize не даст вам ни символа замены, ни полезного совета. К сожалению, этот символ не представлен в ASCII. Таким образом, вы получите ошибки.

Упомянутый модуль лучше справляется с этой задачей. Это на самом деле заменит «æ» на «ae». Что на самом деле полезно и имеет смысл.

Самое впечатляющее, что я видел, это то, что это идет намного дальше. Он даже заменяет символы японской каны в основном должным образом. Например, он заменяет «は» на «ха». Это прекрасно. Это не защищено от ошибок, хотя текущая версия заменяет «ち» на «ti» вместо «chi». Поэтому вам придется с осторожностью обращаться с более экзотическими персонажами.

Использование модуля не вызывает затруднений ::

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

Обратите внимание, что я не имею никакого отношения к этому модулю напрямую. Просто так получается, что я нахожу это очень полезным.

Редактировать: Представленный мною патч исправил ошибку, касающуюся японской каны. Я только исправил тот, который мог заметить сразу. Возможно, я что-то пропустил.

3 голосов
/ 31 мая 2009

Следующая функция является общей:

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")
καλημερα

Очевидно, вы должны знать кодировку своих строк.

1 голос
/ 30 мая 2009

Метод перевода позволяет удалять символы. Вы можете использовать это для удаления произвольных символов.

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

Если вы хотите удалить целые классы символов, вы можете использовать модуль re.

re.sub('[^a-z0-9 ]', '', Fullname.strip().lower(),) 
1 голос
/ 30 мая 2009

Я бы сделал что-то подобное

# 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",
    " ":"."
})

Второй аргумент - это набор символов, которые вы хотите заменить, все не a-z и. символы, которые не были заменены, будут удалены

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...