簡體   English   中英

如何使用哈希圖從Java中的Unicode字符串中刪除重音符號?

[英]How to remove accents from a unicode string in java using a hashmap?

我正在使用以下鏈接來創建鍵= Unicode字符值的哈希圖,值是應映射到的實際字符-https: //github.com/lmjabreu/solr-conftemplate/blob/master/mapping-ISOLatin1Accent。文本

到目前為止,我已經編寫了以下代碼來刪除字符串中的重音符號

public class ACCENTS {

    public static void main(String[] args){

        // this is the hashmap that stores the mappings of the characters to their ascii equivalent
        HashMap<Character, Character> characterMappings = new HashMap<>();

        characterMappings.put('\u00C0', 'A');
        characterMappings.put('\u00C1', 'A');
        characterMappings.put('\u00C2', 'A');
        characterMappings.put('\u00C3', 'A');
        characterMappings.put('\u00C4', 'A');
        characterMappings.put('\u00C5', 'A');
        characterMappings.put('\u00C7','C');
        characterMappings.put('\u00C8', 'E');
        characterMappings.put('\u00C9','E');
        characterMappings.put('\u00CA', 'E');
        characterMappings.put('\u00CB', 'E');
        characterMappings.put('\u00CC', 'I');
        characterMappings.put('\u00CD', 'I');
        characterMappings.put('\u00CE', 'I');
        characterMappings.put('\u00CF', 'I');
        characterMappings.put('\u00D0', 'D');
        characterMappings.put('\u00D1', 'N');
        characterMappings.put('\u00D2', 'O');
        characterMappings.put('\u00D3', 'O');
        characterMappings.put('\u00D4', 'O');
        characterMappings.put('\u00D5', 'O');
        characterMappings.put('\u00D6', 'O');
        characterMappings.put('\u00D8', 'O');
        characterMappings.put('\u00D9', 'U');
        characterMappings.put('\u00DA', 'U');
        characterMappings.put('\u00DB', 'U');
        characterMappings.put('\u00DC', 'U');
        characterMappings.put('\u00DD', 'Y');
        characterMappings.put('\u0178', 'Y');
        characterMappings.put('\u00E0', 'a');
        characterMappings.put('\u00E1', 'a');
        characterMappings.put('\u00E2', 'a');
        characterMappings.put('\u00E3','a');
        characterMappings.put('\u00E4', 'a');
        characterMappings.put('\u00E5', 'a');
        characterMappings.put('\u00E7', 'c');
        characterMappings.put('\u00E8', 'e');
        characterMappings.put('\u00E9', 'e');
        characterMappings.put('\u00EA','e');
        characterMappings.put('\u00EB', 'e');
        characterMappings.put('\u00EC', 'i');
        characterMappings.put('\u00ED', 'i');
        characterMappings.put('\u00EE', 'i');
        characterMappings.put('\u00EF', 'i');
        characterMappings.put('\u00F0', 'd');
        characterMappings.put('\u00F1','n' );
        characterMappings.put('\u00F2', 'o');
        characterMappings.put('\u00F3', 'o');
        characterMappings.put('\u00F4', 'o');
        characterMappings.put('\u00F5', 'o');
        characterMappings.put('\u00F6', 'o');
        characterMappings.put('\u00F8', 'o');
        characterMappings.put('\u00F9', 'u');
        characterMappings.put('\u00FA', 'u');
        characterMappings.put('\u00FB', 'u');
        characterMappings.put('\u00FC', 'u');
        characterMappings.put('\u00FD', 'y');
        characterMappings.put('\u00FF', 'y');

        String token = "nа̀ра";
        String newString = "";


        for(int i = 0 ; i < token.length() ; ++i){
            if( characterMappings.containsKey(token.charAt(i)) )
                newString += characterMappings.get(token.charAt(i));
            else
                newString += token.charAt(i);
        }

        System.out.println(newString);
    }
}

預期結果應該是“ napa”,但事實證明沒有執行任何轉換,這可能是導致這種情況偏離的原因,我找不到。

不知道為什么要使用HashMap。 但是,如果您只想刪除變音符號,則可能會有所幫助:

String s = "nа̀ра";
s = Normalizer.normalize( s, Normalizer.Form.NFD );
s = s.replaceAll("\\p{InCombiningDiacriticalMarks}+", "");
System.out.println( s );

->納帕

(如果您堅持使用HashMap,則應該再看看'Normalizer'類,因為它也可以在另一個方向上工作。)

摘自本文: http : //blog.smartkey.co.uk/2009/10/how-to-strip-accents-from-strings-using-java-6/

您遇到了Java的一些最丑陋的“特征”:一個unicode字符可能由一個字符的tupel(甚至是tripel)來表示。

實際上,令牌的長度為5個字符。 á是兩個字符的組合,只能表示為字符串。

這就是為什么

 characterMappings.put('а̀`', 'y'); //(accent can't be displayed correctly in code-mode, try it yourself)

不會編譯。

是更多說明。

在我看來,String是Java中最差的類之一。 特別是如果您使用“非標准”字符。

為了解決您的問題,我建議將地圖更改為Map<String,String>Map<String,Character> 這樣,您就可以映射“字符”,並且,如果您消除了轉義的unicode字符,那么整潔的副作用將使您的代碼更具可讀性。

有關更多信息,請谷歌查詢HighSurrogate或CodePoint。 代碼點是有效的(=可顯示的)字符序列,如前所述,這些字符序列不必一定與字符串中的字符數相對應。

這是必需的,因為Java字符只有2個字節寬。 對於所有unicode字符,請減小為該大小,但在大多數情況下要足夠大(=,只要您使用標准的拉丁字符即可)。

編輯:

即使使用Map<String,String> ,您的代碼也無法正常工作,因為您仍然會遍歷char。 但是沒有一個Java字符會與您的特殊unicode字符匹配。

這可能會有所幫助,盡管在任何情況下都可能不起作用(畢竟Java字符串很討厭):

HashMap<String, String> characterMappings = new HashMap<>();
characterMappings.put("а̀", "a");

String token = "nа̀ра";
String newString = "";

for (Entry<String, String> e : characterMappings.entrySet()) {
    token = token.replaceAll(e.getKey(), e.getValue());
}
System.out.println(token);

編輯2

由於將代碼作為注釋發布很爛:

    String s = "brûlée";
    String s1 = Normalizer.normalize(s, Normalizer.Form.NFKD);
    String regex = "[\\p{InCombiningDiacriticalMarks}\\p{IsLm}\\p{IsSk}]+";

    String s2 = new String(s1.replaceAll(regex, "").getBytes("ascii"),
            "ascii");

    System.out.println(s2);

到目前為止,我所做的一切都對我有用。 @Scheintod仍然值得贊揚。 這里找到源

最好的祝福

SAM

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM