Si consideri il seguente scambio sui IPython:Python: ottenere corretta lunghezza della stringa quando contiene le coppie di surrogati
In [1]: s = u'華袞與緼同歸'
In [2]: len(s)
Out[2]: 8
L'output corretto avrebbe dovuto essere 7
, ma perché il quinto di questi sette caratteri cinesi ha un codice di alta Unicode -point, è rappresentato in UTF-8 da una "coppia surrogata", piuttosto che da un semplice punto di codice, e come risultato Python pensa che siano due caratteri anziché uno.
Anche se io uso unicodedata
, che restituisce la coppia di surrogati correttamente come un unico codepoint (\U00026177
), quando passa alla len()
della lunghezza sbagliata è ancora restituito:
In [3]: import unicodedata
In [4]: unicodedata.normalize('NFC', s)
Out[4]: u'\u83ef\u889e\u8207\u7dfc\U00026177\u540c\u6b78'
In [5]: len(unicodedata.normalize('NFC', s))
Out[5]: 8
Senza prendere misure drastiche come ricompilare Python per UTF-32, c'è un modo semplice per ottenere la lunghezza corretta in situazioni come questa?
Sono su IPython 0.13, Python 2.7.2, Mac OS 10.8.2.
Le discussioni [qui] (http://stackoverflow.com/questions/9934752/platform-specific-unicode-semantics-in-python-2-7) e [qui] (http://stackoverflow.com/ questions/6922480/how-to-get-a-reliable-unicode-character-count-in-python) sembrano rilevanti. – DSM
@DSM: Grazie per averli scoperti. Il tuo primo link mostra Python compilato per UTF-32 ("wide build"), qualcosa che ho escluso nella mia domanda. Nel secondo, la risposta di wberry mostra un elaborato codice per contare effettivamente i veri personaggi. La mia soluzione predefinita è come quest'ultima, ma spero che esista qualcosa di integrato e più diretto. – brannerchinese
Non riesco a riprodurre qui il risultato (Ubuntu box, python 2.7.2). Per l'unicode u '\ u83ef \ u89i \ u8207 \ u7dfc \ U00026177 \ u540c \ u6b78' ottengo una lunghezza di sette con entrambi len (s) e len (unicode.normalize ('NFC', s)) – Vicent