latin-1 do ascii

Mam ciąg Unicode z akcentowanymi znakami łacińskimi, np.

n=unicode('Wikipédia, le projet d’encyclopédie','utf-8')

Chcę przekonwertować go na zwykły ascii tj. „Wikipedia, le projet dencyclopedie”, więc wszystkie ostre / akcentowane, cedilla itp. Powinny zostać usunięte

Jaki jest najszybszy sposób, aby to zrobić, ponieważ trzeba było to zrobić, aby dopasować długą listę rozwijaną autouzupełniania

Wniosek: Jako że jednym z moich kryteriów jest szybkość, Lennart „rejestruje swój własny program obsługi błędów dla kodowania / dekodowania Unicode” daje najlepszy wynik (patrz odpowiedź Alexa), różnica prędkości wzrasta dalej, ponieważ coraz więcej znaków jest łacińskich.

Oto tablica tłumaczeń, której używam, także zmodyfikowałem procedurę obsługi błędów, ponieważ musi ona zadbać o cały zakres niekodowanych znaków z błędu.start na error.end

# -*- coding: utf-8 -*-
import codecs

"""
This is more of visual translation also avoiding multiple char translation
e.g. £ may be written as {pound}
"""
latin_dict = {
u"¡": u"!", u"¢": u"c", u"£": u"L", u"¤": u"o", u"¥": u"Y",
u"¦": u"|", u"§": u"S", u"¨": u"`", u"©": u"c", u"ª": u"a",
u"«": u"<<", u"¬": u"-", u"­": u"-", u"®": u"R", u"¯": u"-",
u"°": u"o", u"±": u"+-", u"²": u"2", u"³": u"3", u"´": u"'",
u"µ": u"u", u"¶": u"P", u"·": u".", u"¸": u",", u"¹": u"1",
u"º": u"o", u"»": u">>", u"¼": u"1/4", u"½": u"1/2", u"¾": u"3/4",
u"¿": u"?", u"À": u"A", u"Á": u"A", u"Â": u"A", u"Ã": u"A",
u"Ä": u"A", u"Å": u"A", u"Æ": u"Ae", u"Ç": u"C", u"È": u"E",
u"É": u"E", u"Ê": u"E", u"Ë": u"E", u"Ì": u"I", u"Í": u"I",
u"Î": u"I", u"Ï": u"I", u"Ð": u"D", u"Ñ": u"N", u"Ò": u"O",
u"Ó": u"O", u"Ô": u"O", u"Õ": u"O", u"Ö": u"O", u"×": u"*",
u"Ø": u"O", u"Ù": u"U", u"Ú": u"U", u"Û": u"U", u"Ü": u"U",
u"Ý": u"Y", u"Þ": u"p", u"ß": u"b", u"à": u"a", u"á": u"a",
u"â": u"a", u"ã": u"a", u"ä": u"a", u"å": u"a", u"æ": u"ae",
u"ç": u"c", u"è": u"e", u"é": u"e", u"ê": u"e", u"ë": u"e",
u"ì": u"i", u"í": u"i", u"î": u"i", u"ï": u"i", u"ð": u"d",
u"ñ": u"n", u"ò": u"o", u"ó": u"o", u"ô": u"o", u"õ": u"o",
u"ö": u"o", u"÷": u"/", u"ø": u"o", u"ù": u"u", u"ú": u"u",
u"û": u"u", u"ü": u"u", u"ý": u"y", u"þ": u"p", u"ÿ": u"y", 
u"’":u"'"}

def latin2ascii(error):
    """
    error is  protion of text from start to end, we just convert first
    hence return error.start+1 instead of error.end
    """
    return latin_dict[error.object[error.start]], error.start+1

codecs.register_error('latin2ascii', latin2ascii)

if __name__ == "__main__":
    x = u"¼ éíñ§ÐÌëÑ » ¼ ö ® © ’"
    print x
    print x.encode('ascii', 'latin2ascii')

Dlaczego wracamerror.start + 1:

zwrócony obiekt błędu może być wieloma znakami i konwertujemy tylko pierwszy z nich, np. jeśli dodamprint error.start, error.end wyjściem obsługi błędów jest

¼ éíñ§ÐÌëÑ » ¼ ö ® © ’
0 1
2 10
3 10
4 10
5 10
6 10
7 10
8 10
9 10
11 12
13 14
15 16
17 18
19 20
21 22
1/4 einSDIeN >> 1/4 o R c '

więc w drugiej linii otrzymujemy znaki od 2-10, ale konwertujemy tylko 2. stąd zwracamy 3 jako punkt kontynuacji, jeśli zwrócimy error.end wyjście to

¼ éíñ§ÐÌëÑ » ¼ ö ® © ’
0 1
2 10
11 12
13 14
15 16
17 18
19 20
21 22
1/4 e >> 1/4 o R c '

Jak widać, część 2-10 została zastąpiona pojedynczym char. Poza tym szybsze byłoby tylko zakodowanie całego zakresu za jednym razem i zwrócenie błędu.end, ale dla celów demonstracyjnych zachowałem to w prosty sposób.

widziećhttp://docs.python.org/library/codecs.html#codecs.register_error po więcej szczegółów

questionAnswers(6)

yourAnswerToTheQuestion