一尘不染

如何比较“相似”的Unicode字符?

c#

我陷入一个令人惊讶的问题。

我在应用程序中加载了一个文本文件,并且有一些逻辑比较具有µ的值。

我意识到即使文本相同,比较值也是错误的。

 Console.WriteLine("μ".Equals("µ")); // returns false
 Console.WriteLine("µ".Equals("µ")); // return true

在后面的行中,字符µ被复制粘贴。

但是,这些可能不是唯一的类似字符。

C#中有什么方法可以比较看起来相同但实际上不同的字符?


阅读 431

收藏
2020-05-19

共1个答案

一尘不染

在很多情况下,你可以正常化比较之前两个Unicode字符的一定范式,他们应该能够匹配。当然,您需要使用哪种规范化形式取决于字符本身。仅仅因为它们
看起来 相似并不一定意味着它们代表相同的角色。您还需要考虑它是否适合您的用例-请参阅Jukka K. Korpela的评论。

对于这种特殊情况,如果您参考Tony的答案中的链接,则会看到U +
00B5
的表显示:

分解希腊小写字母MU(U + 03BC)

这意味着U + 00B5(原始比较中的第二个字符)可以分解为U + 03BC(第一个字符)。

因此,您将使用完全兼容分解以及标准化形式KC或KD来标准化字符。这是我写来演示的一个简单示例:

using System;
using System.Text;

class Program
{
    static void Main(string[] args)
    {
        char first = 'μ';
        char second = 'µ';

        // Technically you only need to normalize U+00B5 to obtain U+03BC, but
        // if you're unsure which character is which, you can safely normalize both
        string firstNormalized = first.ToString().Normalize(NormalizationForm.FormKD);
        string secondNormalized = second.ToString().Normalize(NormalizationForm.FormKD);

        Console.WriteLine(first.Equals(second));                     // False
        Console.WriteLine(firstNormalized.Equals(secondNormalized)); // True
    }
}

有关Unicode规范化和不同规范化形式的详细信息,请参见System.Text.NormalizationFormUnicode规范

2020-05-19