当前位置: 首页 > 面试题库 >

Java从Unicode字符中删除变音符(criticalñṅņṋṉɳȵȵ)

汝天宇
2023-03-14
问题内容

我正在寻找一种算法,该算法可以在带有变音符号的字符(tilde,circumflex,caret,umlaut,caron)与其“简单”字符之间进行映射。

例如:

ń  ǹ  ň  ñ  ṅ  ņ  ṇ  ṋ  ṉ  ̈  ɲ  ƞ ᶇ ɳ ȵ  --> n
á --> a
ä --> a
ấ --> a
ṏ --> o

等等。

  1. 我想用Java做到这一点,尽管我怀疑它应该是Unicode-y,并且应该可以轻松地以任何语言进行操作。

  2. 目的:允许轻松搜索带有变音标记的单词。例如,如果我有一个网球运动员数据库,并且输入了Björn_Borg,我还将保留Bjorn_Borg,以便在有人进入Bjorn而不是Björn的情况下可以找到它。


问题答案:

我最近在Java中完成了此操作:

public static final Pattern DIACRITICS_AND_FRIENDS
    = Pattern.compile("[\\p{InCombiningDiacriticalMarks}\\p{IsLm}\\p{IsSk}]+");

private static String stripDiacritics(String str) {
    str = Normalizer.normalize(str, Normalizer.Form.NFD);
    str = DIACRITICS_AND_FRIENDS.matcher(str).replaceAll("");
    return str;
}

这将按照你指定的方式进行:

stripDiacritics("Björn")  = Bjorn

但由于诸如Białystok之类的ł人物不讲字,因此它将失败。

如果要使用功能强大的字符串简化程序,则需要进行第二轮清理,以获取一些不是变音符号的特殊字符。是这张地图,我包括了出现在我们客户名称中的最常见的特殊字符。它不是一个完整的列表,但是会为你提供扩展方法的想法。immutableMap只是google-collections中的一个简单类。

public class StringSimplifier {
    public static final char DEFAULT_REPLACE_CHAR = '-';
    public static final String DEFAULT_REPLACE = String.valueOf(DEFAULT_REPLACE_CHAR);
    private static final ImmutableMap<String, String> NONDIACRITICS = ImmutableMap.<String, String>builder()

        //Remove crap strings with no sematics
        .put(".", "")
        .put("\"", "")
        .put("'", "")

        //Keep relevant characters as seperation
        .put(" ", DEFAULT_REPLACE)
        .put("]", DEFAULT_REPLACE)
        .put("[", DEFAULT_REPLACE)
        .put(")", DEFAULT_REPLACE)
        .put("(", DEFAULT_REPLACE)
        .put("=", DEFAULT_REPLACE)
        .put("!", DEFAULT_REPLACE)
        .put("/", DEFAULT_REPLACE)
        .put("\\", DEFAULT_REPLACE)
        .put("&", DEFAULT_REPLACE)
        .put(",", DEFAULT_REPLACE)
        .put("?", DEFAULT_REPLACE)
        .put("°", DEFAULT_REPLACE) //Remove ?? is diacritic?
        .put("|", DEFAULT_REPLACE)
        .put("<", DEFAULT_REPLACE)
        .put(">", DEFAULT_REPLACE)
        .put(";", DEFAULT_REPLACE)
        .put(":", DEFAULT_REPLACE)
        .put("_", DEFAULT_REPLACE)
        .put("#", DEFAULT_REPLACE)
        .put("~", DEFAULT_REPLACE)
        .put("+", DEFAULT_REPLACE)
        .put("*", DEFAULT_REPLACE)

        //Replace non-diacritics as their equivalent characters
        .put("\u0141", "l") // BiaLystock
        .put("\u0142", "l") // Bialystock
        .put("ß", "ss")
        .put("æ", "ae")
        .put("ø", "o")
        .put("©", "c")
        .put("\u00D0", "d") // All Ð ð from http://de.wikipedia.org/wiki/%C3%90
        .put("\u00F0", "d")
        .put("\u0110", "d")
        .put("\u0111", "d")
        .put("\u0189", "d")
        .put("\u0256", "d")
        .put("\u00DE", "th") // thorn Þ
        .put("\u00FE", "th") // thorn þ
        .build();


    public static String simplifiedString(String orig) {
        String str = orig;
        if (str == null) {
            return null;
        }
        str = stripDiacritics(str);
        str = stripNonDiacritics(str);
        if (str.length() == 0) {
            // Ugly special case to work around non-existing empty strings
            // in Oracle. Store original crapstring as simplified.
            // It would return an empty string if Oracle could store it.
            return orig;
        }
        return str.toLowerCase();
    }

    private static String stripNonDiacritics(String orig) {
        StringBuffer ret = new StringBuffer();
        String lastchar = null;
        for (int i = 0; i < orig.length(); i++) {
            String source = orig.substring(i, i + 1);
            String replace = NONDIACRITICS.get(source);
            String toReplace = replace == null ? String.valueOf(source) : replace;
            if (DEFAULT_REPLACE.equals(lastchar) && DEFAULT_REPLACE.equals(toReplace)) {
                toReplace = "";
            } else {
                lastchar = toReplace;
            }
            ret.append(toReplace);
        }
        if (ret.length() > 0 && DEFAULT_REPLACE_CHAR == ret.charAt(ret.length() - 1)) {
            ret.deleteCharAt(ret.length() - 1);
        }
        return ret.toString();
    }

    /*
    Special regular expression character ranges relevant for simplification -> see http://docstore.mik.ua/orelly/perl/prog3/ch05_04.htm
    InCombiningDiacriticalMarks: special marks that are part of "normal" ä, ö, î etc..
        IsSk: Symbol, Modifier see http://www.fileformat.info/info/unicode/category/Sk/list.htm
        IsLm: Letter, Modifier see http://www.fileformat.info/info/unicode/category/Lm/list.htm
     */
    public static final Pattern DIACRITICS_AND_FRIENDS
        = Pattern.compile("[\\p{InCombiningDiacriticalMarks}\\p{IsLm}\\p{IsSk}]+");


    private static String stripDiacritics(String str) {
        str = Normalizer.normalize(str, Normalizer.Form.NFD);
        str = DIACRITICS_AND_FRIENDS.matcher(str).replaceAll("");
        return str;
    }
}


 类似资料:
  • 问题内容: 可能吗?这是我的输入字符串: 这是我想要的输出: 问题答案: Wordpress使用了一个功能,效果很好。这是带有输出的工作代码。

  • 问题内容: 如何从字符串中删除变音符号? 例如,转换适用于所有语言的所有á-> a,č-> c等。 我正在进行全文搜索,因此需要忽略搜索文字的任何变音符号。 谢谢 问题答案: 使用9级以上的API,您可以使用Normalizer类,例如 (Keysers链接的答案看起来更好,它可以清除更多废话) 这将返回。

  • 问题内容: 我想改变这句话: 等等。 至 : 等等。 有没有像我在Objective-C中那样在Java中执行此操作的简便方法? 问题答案: 最后,我通过使用类解决了它。

  • 问题内容: 我正在制作瑞典语网站,瑞典语字母是å,ä和ö。 我需要创建一个用户输入的字符串,以使用PHP进行网址安全。 基本上,需要将所有字符都转换为下划线,除以下字符外: 并且所有瑞典语都应该这样转换: “å”到“ a”,“ä”到“ a”,“ö”到“ o”(只需删除上面的点)。 正如我所说,其余的应该成为下划线。 我不太擅长使用正则表达式,因此我非常感谢您的帮助! 谢谢 注意:不是URLENCO

  • 问题内容: (据我所知)Android中是否有任何方法都没有java.text.Normalizer从字符串中删除任何重音符号。例如,“éàù”变成“ eau”。 如果可能,我想避免解析String来检查每个字符! 问题答案: 在Android中可用(无论如何都是最新版本)。您可以使用它。 编辑 供参考,这里是如何使用: (从下面评论中的链接粘贴)

  • 问题内容: 如何从Swift中删除变音符号(或重音符号)(例如说将“één”更改为“ een”)?我必须回到Swift还是可以在Swift中完成? 问题答案: 您可以直接在Swift上操作(如果导入了“ Foundation”): 斯威夫特3: