【问题标题】:Removing diacritics in Polish删除波兰语中的变音符号
【发布时间】:2011-04-03 10:00:50
【问题描述】:

我正在尝试从波兰语的 pangram 中删除变音符号。我正在使用 Michael Kaplan 的博客 http://www.siao2.com/2007/05/14/2629747.aspx 中的代码,但是没有成功。

考虑以下 pangram:“Pchnąć w tę łódź jeża lub ośm skrzyń fig.”。一切正常,但对于字母“ł”,我仍然得到“ł”。我想问题是“ł”表示为单个 unicode 字符,并且没有后续的 NonSpacingMark。

您知道如何修复它(不依赖某些字典中的自定义映射 - 我正在寻找某种 unicode 转换)?

【问题讨论】:

    标签: c# .net unicode diacritics polish


    【解决方案1】:

    我找到了也处理“ł”的解决方案

    string RemoveDiacritics(string text)
        {
            var normalizedString = text.Normalize(NormalizationForm.FormD);
            var stringBuilder = new StringBuilder();
    
            foreach (var c in normalizedString)
            {
                var unicodeCategory = CharUnicodeInfo.GetUnicodeCategory(c);
                if (unicodeCategory != UnicodeCategory.NonSpacingMark)
                {
                    stringBuilder.Append(c);
                }
            }
    
            return stringBuilder.ToString().Normalize(NormalizationForm.FormC);
        }
    

    【讨论】:

      【解决方案2】:

      前段时间我遇到了这个解决方案,它似乎工作正常:

          public static string RemoveDiacritics(this string s)
          {
              string asciiEquivalents = Encoding.ASCII.GetString(
                           Encoding.GetEncoding("Cyrillic").GetBytes(s)
                       );
      
              return asciiEquivalents;
          }
      

      【讨论】:

      • System.ArgumentException : 'Cyrillic' is not a supported encoding name. 我还需要转换法语,但我认为它无论如何都行不通:( 德语呢?
      【解决方案3】:

      这是我对波兰语变音符号规范化的波兰语停止列表的快速实现。

          class StopList
      {
          private HashSet<String> set = new HashSet<String>();
      
          public void add(String word)
          {
              word = word.trim().toLowerCase();
              word = normalize(word);
              set.add(word);
      
          }
      
          public boolean contains(final String string)
          {
              return set.contains(string) || set.contains(normalize(string));
          }
      
          private char normalizeChar(final char c)
          {
              switch ( c)
              {
                  case 'ą':
                      return 'a';
                  case 'ć':
                      return 'c';
                  case 'ę':
                      return 'e';
                  case 'ł':
                      return 'l';
                  case 'ń':
                      return 'n';
                  case 'ó':
                      return 'o';
                  case 'ś':
                      return 's';
                  case 'ż':
                  case 'ź':
                      return 'z';
              }
              return c;
          }
      
          private String normalize(final String word)
          {
              if (word == null || "".equals(word))
              {
                  return word;
              }
              char[] charArray = word.toCharArray();
              char[] normalizedArray = new char[charArray.length];
              for (int i = 0; i < normalizedArray.length; i++)
              {
                  normalizedArray[i] = normalizeChar(charArray[i]);
              }
              return new String(normalizedArray);
          }
      }
      

      我在网上找不到任何其他解决方案。所以也许它会对某人有帮助(?)

      【讨论】:

      • 期望ł 所有这些字符都只有diacritics(我至少看到了ogonek、accent 和dot),并且可以使用Normalize 轻松标准化。我建议将这两种方法结合起来。
      • 规范化是 .NET 库吗?抱歉...这是我的 Java 代码中的 sn-p :) 写“Net”时我在考虑 Internet,而不是“.NET”。
      • 手动总是一个选项,但我应该写所有组合吗?法语、德语、波兰语等?
      【解决方案4】:

      您必须手动替换这些(就像 Latin-1 中的 ÆÐØÞßæðøþ)。

      其他人也遇到过同样的问题,因此 Unicode 通用语言环境数据存储库“同意添加一个音译器来去除重音,即使是重叠的重音也是如此。” (Ticket #2884)

      【讨论】:

        【解决方案5】:

        有很多预先组合的字符没有有意义的分解。

        (也有少数可以进行合理的分解,在大多数规范化形式中禁止这种分解,因为这会导致版本之间的差异,这将使它们不再真正规范化)。

        ł 就是其中之一。 IIRC 也不可能对不使用 ł 的字母进行文化中立的转录。我认为德国人倾向于将其转录为 w 而不是 l(或者可能是其他人这样做),这是有道理的(听起来也不太正确,但它比 l 更接近)。

        【讨论】:

          【解决方案6】:

          它位于Unicode chart,代码点\u0142。向下滚动到描述“带有笔划的拉丁小写字母”,它没有列出分解。对波兰语一无所知,但一个字母通常有一个区别标记,使其成为自己的字母,而不是带有变音符号的基本字母。

          【讨论】:

            【解决方案7】:

            文章中采用的方法是去掉 Mark, Nonspacing 字符。由于您正确指出“ł”不是由两个字符组成(其中一个是标记,非空格),因此您看到的行为是预期的。

            我不认为 Unicode 的结构可以让你完成完全自动化的重新映射(你引用的文章的作者得出了同样的结论)。

            如果您只对波兰字符感兴趣,那么至少映射很小且定义明确(例如,请参见 http://www.biega.com/special-char.html 的底部)。对于一般情况,我认为对于不是由标准字符加上标记、非间距字符组成的字符,不存在自动化解决方案。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2019-03-01
              • 2016-12-09
              • 2018-04-10
              • 1970-01-01
              • 2013-10-10
              • 1970-01-01
              • 2017-04-11
              相关资源
              最近更新 更多