【问题标题】:Comparing visually similar strings in C#在 C# 中比较视觉上相似的字符串
【发布时间】:2021-12-02 16:50:05
【问题描述】:

如果这是一个明显的问题,这里的新程序员非常抱歉。 我需要在 C# 中编写一段非常简单的代码(作为练习,所以没有要连接的数据库)来比较两个视觉上相似的字符串,例如FOX 和 F0X。

据我所知,大多数比较方法都会返回说它们不相似,因为 O 和 0 是不同的字符,所以我不知道该怎么做!

任何指针将不胜感激!谢谢

【问题讨论】:

  • 使用类字符串比较?
  • 您对视觉上相似的含义有什么规定吗?鉴于 Unicode 字符种类繁多,该列表将非常长。最简单的方法是使用 canonicalized 表示(例如将零更改为大写 Os 等),用于两个字符串
  • 所以规则是 FOX 和 F0X 相似,BBB 和 B B B 相似但 ABC 和 DEF 不相似。这只是一个非常简单的练习,在测试中使用了一些硬编码的字符串。我查看了字符串比较,但我认为它会说 FOX 和 F0X 不相似,因为 O 和零是不同的字符 - 除非我误解了?
  • 嗯,我想也许可以在这里跳出框框思考-听起来您需要图像分析而不是文本。或者写一些复杂的定制规则来描述看起来相似的单词序列。

标签: c# string compare


【解决方案1】:

这不是一项微不足道的任务,并且没有单一的预定义方法可以做到这一点。

但是考虑一下你可能会如何处理它,你可能需要从建立一组规则开始,以确定你认为哪些角色看起来相似。然后在比较字符时查找这些规则。

类似的东西。

string[] SimilarCharacters = new string[]
{
    "O0",
    "I1"
    // Etc...
};

void Main()
{
    Console.WriteLine(AreSimilar("FOX", "F0X"));
    Console.WriteLine(AreSimilar("BOX", "B0X"));
    Console.WriteLine(AreSimilar("FIG", "F1G"));
    Console.WriteLine(AreSimilar("J1G", "JIG"));
}

bool AreSimilar(string s1, string s2)
{
    // No match if different lengths
    if (s1.Length != s2.Length)
        return false;

    for (int i = 0; i < s1.Length; i++)
    {
        if (s1[i] != s2[i])
        {
            string similar = FindSimilar(s1[i]);
            if (similar == null)
                return false;
                
            if (!similar.Contains(s2[i]))
                return false;
        }
    }
    return true;
}

string FindSimilar(char c)
{
    for (int i = 0; i < SimilarCharacters.Length; i++)
    {
        if (SimilarCharacters[i].Contains(c))
            return SimilarCharacters[i];
    }
    return null;
}

【讨论】:

    【解决方案2】:

    我认为适当的方法是用其中一个替换所有相似的字符(或字符集)。即:用“O”替换所有“O”和“0”(反之亦然)。这样,你就只有一个角色需要关注。请注意,您必须考虑大写和小写,因为我假设您不希望将“o”替换为“O”(或者您可能会这样做。)无论哪种方式,我认为这是一个好方法。

            using System.Text;
            
            (...)
    
            string a = "0()P is e><ce1|ent"; //OOP, Object Oriented Programming
            StringBuilder b = new StringBuilder();
    
            bool parenthesesZero = false;
            bool greaterThanX = false;
    
            for (int i = 0; i < a.Length; i++)
            {
                switch (a[i])
                {
                    case '0':
                        b.Append('O');
                        break;
                    case '(':
                        b.Append('(');
                        parenthesesZero = true;
                        break;
                    case ')':
                        if (parenthesesZero)
                        {
                            b[i - 1] = 'O';
                            parenthesesZero = false;
                        }
                        else
                            b.Append(')');
                        break;
                    case '>':
                        b.Append('>');
                        greaterThanX = true;
                        break;
                    case '<':
                        if (greaterThanX)
                        {
                            b[b.Length - 1] = 'X';
                            greaterThanX = false;
                        }
                        else
                            b.Append('<');
                        break;
                    case '|':
                    case 'I':
                    case '1':
                        b.Append('l');
                        break;
                    default:
                        b.Append(a[i]);
                        break;
                }
            }
                
    
            Console.WriteLine(a + "\n" + b);
    

    请注意我如何使用 fallthrough 将一组相似字符集中到一个中,以及我如何跟踪可能被一个(或多个)字符替换的多个字符序列。如果您有两个以上的字符,可以考虑使用整数计数器。

    这可能不是最好的答案,但我希望你认为它有用。

    美好的一天!

    【讨论】:

      猜你喜欢
      • 2010-10-19
      • 2011-10-20
      • 1970-01-01
      • 2011-08-17
      • 1970-01-01
      • 2010-10-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多