有没有一种方法可以去除重音符号并将整个字符串转换为普通字母?

323

除了使用String.replaceAll()方法并逐个替换字母外,是否有更好的方法来去除重音并使这些字母规范化?

例如:

输入:orčpžsíáýd

输出:orcpzsiayd

它不需要包括所有带重音符号的字母,如俄语或中文字母。

15个回答

2

@David Conrad的解决方案是我尝试过的最快的,但它确实有一个bug。它基本上会剥离掉不是重音符号的字符,例如中文字符和其他字母如æ都被剥离了。 我们想要剥离的字符是非间隔标记,即在最终字符串中不占用额外宽度的字符。这些零宽度字符基本上会与其他字符组合在一起。如果你能看到它们单独作为一个字符,例如像这样',我猜测它是与空格字符结合在一起的。

public static String flattenToAscii(String string) {
    char[] out = new char[string.length()];
    String norm = Normalizer.normalize(string, Normalizer.Form.NFD);

    int j = 0;
    for (int i = 0, n = norm.length(); i < n; ++i) {
        char c = norm.charAt(i);
        int type = Character.getType(c);

        //Log.d(TAG,""+c);
        //by Ricardo, modified the character check for accents, ref: https://dev59.com/12025IYBdhLWcg3w96wW#5697575
        if (type != Character.NON_SPACING_MARK){
            out[j] = c;
            j++;
        }
    }
    //Log.d(TAG,"normalized string:"+norm+"/"+new String(out));
    return new String(out);
}

0

遇到了同样的问题,这里提供使用 Kotlin 扩展的解决方案

   val String.stripAccents: String
    get() = Regex("\\p{InCombiningDiacriticalMarks}+")
        .replace(
            Normalizer.normalize(this, Normalizer.Form.NFD),
            ""
        )

用法

val textWithoutAccents = "some accented string".stripAccents

0

一种更快、更安全的方式

public static String removeDiacritics(String str) {
    if (str == null)
        return null;
    if (str.isEmpty())
        return "";
    
    int len = str.length();
    StringBuilder sb
        = new StringBuilder(len);
    
    //iterate string codepoints
    for (int i = 0; i < len; ) {
        int codePoint = str.codePointAt(i);
        int charCount
            = Character.charCount(codePoint);
        
        if (charCount > 1) {
            for (int j = 0; j < charCount; j++)
                sb.append(str.charAt(i + j));
            i += charCount;
            continue;
        }
        else if (codePoint <= 127) {
            sb.append((char)codePoint);
            i++;
            continue;
        }
        
        sb.append(
            java.text.Normalizer
                .normalize(
                    Character.toString((char)codePoint),
                    java.text.Normalizer.Form.NFD)
                        .charAt(0));
        i++;
    }
    
    return sb.toString();
}

0

我认为最好的解决方案是将每个字符转换为十六进制,并用另一个十六进制替换它。这是因为有两种Unicode输入法:

Composite Unicode
Precomposed Unicode

例如,由複合Unicode寫成的“Ồ”與由預組Unicode寫成的“Ồ”是不同的。您可以複製我的樣本字符並進行轉換以查看差異。
In Composite Unicode, "Ồ" is combined from 2 char: Ô (U+00d4) and ̀ (U+0300)
In Precomposed Unicode, "Ồ" is single char (U+1ED2)

我曾为一些银行开发了这个功能,以便在将信息发送到核心银行之前进行转换(通常不支持Unicode),但当最终用户使用多种Unicode输入方式输入数据时,我遇到了这个问题。因此,我认为将其转换为十六进制并进行替换是最可靠的方法。


-2

如果有人在Kotlin中遇到困难,这段代码非常好用。为了避免不一致性,我还使用了.toUpperCase和Trim()。然后我将此函数转换:

   fun stripAccents(s: String):String{

   if (s == null) {
      return "";
   }

val chars: CharArray = s.toCharArray()

var sb = StringBuilder(s)
var cont: Int = 0

while (chars.size > cont) {
    var c: kotlin.Char
    c = chars[cont]
    var c2:String = c.toString()
   //these are my needs, in case you need to convert other accents just Add new entries aqui
    c2 = c2.replace("Ã", "A")
    c2 = c2.replace("Õ", "O")
    c2 = c2.replace("Ç", "C")
    c2 = c2.replace("Á", "A")
    c2 = c2.replace("Ó", "O")
    c2 = c2.replace("Ê", "E")
    c2 = c2.replace("É", "E")
    c2 = c2.replace("Ú", "U")

    c = c2.single()
    sb.setCharAt(cont, c)
    cont++

}

return sb.toString()

}

要使用这些函数,请像这样转换代码:

     var str: String
     str = editText.text.toString() //get the text from EditText
     str = str.toUpperCase().trim()

     str = stripAccents(str) //call the function

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接