如何将字符串减少到ASCII 7个字符以进行索引



我正在处理必须索引某些句子的应用程序。当前使用Java和PostgreSQL。这些句子可能使用多种语言,例如法语和西班牙语,使用口音和其他非ASCII符号。

对于每个单词,我想创建一个可索引的同等标准,以便用户可以对口音(音译)执行搜索不敏感。例如,当用户搜索" nacion"时,即使应用程序存储的原始单词为" naci ó n"。

最好的策略是什么?我不一定仅限于postgresql,也不一定要与原始单词具有任何相似之处。理想情况下,它应该是将任何Unicode字符串转换为对案例和口音不敏感的通用解决方案。

到目前为止,我正在使用下面显示的自定义功能,该功能天真地将某些字母替换为ASCII等效物,然后存储索引值并在查询字符串上进行相同的字母。

public String toIndexableASCII (String sStrIn) {
  if (sStrIn==null) return null;
  int iLen = sStrIn.length();
  if (iLen==0) return sStrIn;
  StringBuilder sStrBuff = new StringBuilder(iLen);
  String sStr = sStrIn.toUpperCase();
  for (int c=0; c<iLen; c++) {
    switch (sStr.charAt(c)) {
      case 'Á':
      case 'À':
      case 'Ä':
      case 'Â':
      case 'Å':
      case 'Ã':
        sStrBuff.append('A');
        break;
      case 'É':
      case 'È':
      case 'Ë':
      case 'Ê':
        sStrBuff.append('E');
        break;
      case 'Í':
      case 'Ì':
      case 'Ï':
      case 'Î':
        sStrBuff.append('I');
        break;
      case 'Ó':
      case 'Ò':
      case 'Ö':
      case 'Ô':
      case 'Ø':
        sStrBuff.append('O');
        break;
      case 'Ú':
      case 'Ù':
      case 'Ü':
      case 'Û':
        sStrBuff.append('U');
        break;
      case 'Æ':
        sStrBuff.append('E');
        break;
      case 'Ñ':
        sStrBuff.append('N');
        break;
      case 'Ç':
        sStrBuff.append('C');
        break;
      case 'ß':
        sStrBuff.append('B');
        break;
      case (char)255:
        sStrBuff.append('_');
        break;
      default:
        sStrBuff.append(sStr.charAt(c));
    }
  }
  return sStrBuff.toString();
}
    String s = "Nación";
    String x = Normalizer.normalize(s, Normalizer.Form.NFD);
    StringBuilder sb=new StringBuilder(s.length());
    for (char c : x.toCharArray()) {
        if (Character.getType(c) != Character.NON_SPACING_MARK) {
            sb.append(c);
        }
    }
    System.out.println(s); // Nación
    System.out.println(sb.toString()); // Nacion

这是如何工作的:它将国际字符分解为NFD分解(ó成为o◌́),然后剥离组合标记。

Character.NON_SPACING_MARK包含结合音位标记(Unicode称其为bidi类NSM [非间隔标记])。

您当前代码的一个明显改进:使用映射使用 preflly Map<Character, Character>

,然后只需检查该地图是否具有映射;这样;使用否则使用原始字符。

正如Androbin所解释的那样,有一些特殊的地图不依赖于对象,而是使用原始类型,例如Trove。因此,取决于您的解决方案和要求;您可以看一下。

相关内容

  • 没有找到相关文章

最新更新