如何比较具有不同字节但具有相同值的Unicode字符串?

Seu*_*aek 56 python unicode

我正在比较JSON对象之间的Unicode字符串.

它们具有相同的价值:

a = '???????????????'
b = '???????????????'
Run Code Online (Sandbox Code Playgroud)

但它们有不同的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'
Run Code Online (Sandbox Code Playgroud)

如何比较两个Unicode字符串的值?

Ry-*_*Ry- 61

Unicode规范化将帮助您实现这一目标:

>>> import unicodedata
>>> unicodedata.normalize("NFC", "\uf9fb") == "\u7099"
True
Run Code Online (Sandbox Code Playgroud)

unicodedata.normalize在比较它们之前使用两个字符串==以检查规范的Unicode等效性.

字符U+F9FB是"CJK兼容性"字符.标准化后,这些字符会分解为一个或多个常规CJK字符.

  • @abarnert:我不想推荐我没有审核过的图书馆,而且不清楚这里是否需要; 随便写下自己的答案.(另外需要更多指令才能有效地使用pyuca.)(编辑:事实证明它没有,我正在考虑PyICU,现在wilx的答案涵盖了,所以请阅读) (15认同)
  • Ry,你为什么要回滚我的修订版?建议人们转换为NFC并进行比较"通常足够好",但这并不是真的正确.UCA存在的原因很充分,而且它不在stdlib中并不意味着没有容易实现的实现. (5认同)
  • 真的应该强调的是,这不会解决所有类别的问题,并且 `==` 是一个你必须考虑的*困难*问题。必须考虑“==”的含义*在每个特定的上下文中*。渲染的一样吗?对使用特定语言的人来说意思相同吗?所有语言?是标识符吗?你想忽略纯粹的渲染差异吗?这是攻击面吗? (2认同)

aba*_*ert 48

字符U+F9FB()是CJK兼容表意文字.这些字符是与常规CJK字符不同的代码点,但在规范化时它们会分解为一个或多个常规CJK字符.

Unicode有一个名为UCA的官方字符串整理算法,专门用于此目的.从3.7开始,Python没有UCA支持*,但是有第三方库,如pyuca:

>>> from pyuca import Collator
>>> ck = Collator().sort_key
>>> ck(a) == ck(b)
True
Run Code Online (Sandbox Code Playgroud)

对于这种情况 - 以及许多其他情况,但绝对不是全部 - 选择适当的规范化以在比较之前应用于两个字符串将起作用,并且它具有内置于stdlib中的支持的优点.

*自3.4以来,这个想法已被原则上接受,但没有人编写实现 - 部分是因为大多数关心的核心开发者正在使用pyuca或者是两个ICU绑定中的一个,这些绑定具有在当前和旧版本中工作的优点.蟒蛇.