python unicode

python - ¿Cómo comparo una cadena Unicode que tiene diferentes bytes, pero el mismo valor?



import unicode python (3)

Estoy comparando cadenas Unicode entre objetos JSON.

Tienen el mismo valor:

a = ''人口じんこうに膾炙かいしゃする'' b = ''人口じんこうに膾炙かいしゃする''

Pero tienen diferentes representaciones Unicode:

String a : u''/u4eba/u53e3/u3058/u3093/u3053/u3046/u306b/u81be/u7099/u304b/u3044/u3057/u3083/u3059/u308b'' String b : u''/u4eba/u53e3/u3058/u3093/u3053/u3046/u306b/u81be/uf9fb/u304b/u3044/u3057/u3083/u3059/u308b''

¿Cómo puedo comparar entre dos cadenas Unicode en su valor?


El personaje U+F9FB (炙) es un ideógrafo de compatibilidad CJK . Estos caracteres son puntos de código distintos de los caracteres CJK normales, pero se descomponen en uno o más caracteres CJK normales cuando se normalizan.

Unicode tiene un algoritmo oficial de clasificación de cadenas llamado UCA diseñado exactamente para este propósito. Python no viene con soporte UCA a partir de 3.7, * pero hay bibliotecas de terceros como pyuca :

>>> from pyuca import Collator >>> ck = Collator().sort_key >>> ck(a) == ck(b) True

Para este caso, y muchos otros, pero definitivamente no todos, elegir la normalización adecuada para aplicar a ambas cadenas antes de comparar funcionará, y tiene la ventaja del soporte integrado en stdlib.

* La idea ha sido aceptada en principio desde 3.4, pero nadie ha escrito una implementación, en parte porque la mayoría de los desarrolladores principales que se preocupan están usando pyuca o uno de los dos enlaces de la UCI, que tienen la ventaja de trabajar en versiones actuales y anteriores de pitón.


Hubiera usado PyICU y su clase Collator. Pero primero, debe pensar en qué nivel del algoritmo de clasificación Unicode desea que ocurra la igualdad.

#!/usr/bin/python # -*- coding: utf-8 -*- from icu import Collator coll = Collator.createInstance() coll.setStrength(Collator.IDENTICAL) a = u''人口じんこうに膾炙かいしゃする'' b = u''人口じんこうに膾炙かいしゃする'' print repr(a) print repr(b) print (''%s == %s : %s'' % (a, b, coll.equals(a,b))) a = u''エレベーター'' b = u''エレベーター'' print (''%s == %s : %s'' % (a, b, coll.equals(a,b))) coll.setStrength(Collator.PRIMARY) print (''%s == %s : %s'' % (a, b, coll.equals(a,b))) a = u''hello'' b = u''HELLO'' coll.setStrength(Collator.PRIMARY) print (''%s == %s : %s'' % (a, b, coll.equals(a,b))) coll.setStrength(Collator.TERTIARY) print (''%s == %s : %s'' % (a, b, coll.equals(a,b)))

Esto produce:

u''/u4eba/u53e3/u3058/u3093/u3053/u3046/u306b/u81be/u7099/u304b/u3044/u3057/u3083/u3059/u308b'' u''/u4eba/u53e3/u3058/u3093/u3053/u3046/u306b/u81be/uf9fb/u304b/u3044/u3057/u3083/u3059/u308b'' 人口じんこうに膾炙かいしゃする == 人口じんこうに膾炙かいしゃする : True エレベーター == エレベーター : False エレベーター == エレベーター : True hello == HELLO : True hello == HELLO : False


La normalización Unicode lo llevará allí para esto:

>>> import unicodedata >>> unicodedata.normalize("NFC", "/uf9fb") == "/u7099" True

Use unicodedata.normalize en ambas cadenas antes de compararlas con == para verificar la equivalencia canónica de Unicode.

El personaje U+F9FB es un personaje de "Compatibilidad CJK". Estos caracteres se descomponen en uno o más caracteres CJK normales cuando se normalizan.