2010-04-16 16 views
5

Chciałbym zastąpić pewien zestaw znaków ciągu z odpowiednią postacią zastępczą w skuteczny sposób.Jak zamienić znaki w łańcuchu java?

Na przykład:

String sourceCharacters = "šđćčŠĐĆČžŽ"; 
String targetCharacters = "sdccSDCCzZ"; 

String result = replaceChars("Gračišće", sourceCharacters , targetCharacters); 

Assert.equals(result,"Gracisce") == true; 

Czy istnieje bardziej efektywny sposób niż użycie metody klasy String replaceAll?

Moja pierwsza myśl była:

final String s = "Gračišće"; 
String sourceCharacters = "šđćčŠĐĆČžŽ"; 
String targetCharacters = "sdccSDCCzZ"; 

// preparation 
final char[] sourceString = s.toCharArray(); 
final char result[] = new char[sourceString.length]; 
final char[] targetCharactersArray = targetCharacters.toCharArray(); 

// main work 
for(int i=0,l=sourceString.length;i<l;++i) 
{ 
    final int pos = sourceCharacters.indexOf(sourceString[i]); 
    result[i] = pos!=-1 ? targetCharactersArray[pos] : sourceString[i]; 
} 

// result 
String resultString = new String(result); 

Jakieś pomysły?

Przy okazji, znaki UTF-8 powodują problem, z US_ASCII działa dobrze.

Odpowiedz

14

Można skorzystać z java.text.Normalizer i strzał regex aby pozbyć się diacritics w których istnieją znacznie ponad zebraniu tak daleko.

Oto SSCCE, copy'n'paste'n'run go na Java 6:

package com.stackoverflow.q2653739; 

import java.text.Normalizer; 
import java.text.Normalizer.Form; 

public class Test { 

    public static void main(String... args) { 
     System.out.println(removeDiacriticalMarks("Gračišće")); 
    } 

    public static String removeDiacriticalMarks(String string) { 
     return Normalizer.normalize(string, Form.NFD) 
      .replaceAll("\\p{InCombiningDiacriticalMarks}+", ""); 
    } 
} 

ta powinna przynieść

Gracisce

Przynajmniej robi tutaj w konsoli Eclipse z charakterem kodowanie ustawione na UTF-8 (Okno> Preferencje> Ogólne> Przestrzeń robocza> Kodowanie pliku tekstowego). Upewnij się, że to samo zostało ustawione w twoim środowisku.

Alternatywnie utrzymać Map<Character, Character>:

Map<Character, Character> charReplacementMap = new HashMap<Character, Character>(); 
charReplacementMap.put('š', 's'); 
charReplacementMap.put('đ', 'd'); 
// Put more here. 

String originalString = "Gračišće"; 
StringBuilder builder = new StringBuilder(); 

for (char currentChar : originalString.toCharArray()) { 
    Character replacementChar = charReplacementMap.get(currentChar); 
    builder.append(replacementChar != null ? replacementChar : currentChar); 
} 

String newString = builder.toString(); 
+0

z tym rozwiązaniem otrzymuję: GraA? IAAAA. i btw, chciałbym wymienić nie tylko znaki diakrytyczne, ale także inne języki w innych językach. więc naprawdę chciałbym poznać rozwiązanie, które działa na dowolne mapowanie. – ManBugra

+1

Dokładnie. Problem polega na tym, że znaki diakrytyczne są czasami łączone, czasami nie, a ciąg znaków zastępuje znak po znaku, ponieważ są w rzeczywistości dwa znaki, a nie jeden. –

+0

@Mr. Shiny and New: yes, System.out.println ("š" .toCharArray(). Length); wyjścia "2" – ManBugra

0

I użyć metody replace w prosty pętli.

String sourceCharacters = "šđćčŠĐĆČžŽ"; 
String targetCharacters = "sdccSDCCzZ"; 

String s = "Gračišće"; 
for (int i=0 ; i<sourceCharacters.length() ; i++) 
    s = s.replace(sourceCharacters.charAt[i], targetCharacters.charAt[i]); 

System.out.println(s); 
+0

każda iteracja tworzyłaby nowy obiekt typu string.Byłoby miło to zrobić "na miejscu" – ManBugra

+0

Po pierwsze, każda iteracja tworzy nowy obiekt tylko po dokonaniu zmiany; jeśli szukany znak nie istnieje, zwracany jest oryginalny obiekt. Po drugie, * bardziej * irytujące jest pisanie tego kodu za pomocą 'StringBuilder' lub' StringBuffer', ponieważ musisz sam wykonać całą pracę; Ponieważ zarządzanie pamięcią w Javie jest dostrojone do szybkiego obracania obiektami, łatwiej jest to zrobić tak, jak pokazałem, zamiast próbować dowiedzieć się, jak być wydajnym. Zawsze możesz zoptymalizować później, jeśli jest to naprawdę konieczne (to znaczy, jeśli jest to prawdziwe wąskie gardło). –

+0

Tak, twoje masz rację w swoim pierwszym punkcie. ale nie zgadzam się z twoim drugim. piszesz kiedyś skuteczny kod, nawet irytujący, i używasz go ponownie. tak czy inaczej BalusC rozwiązał zagadkę. – ManBugra

Powiązane problemy