2011-09-19 8 views
18

Załóżmy, że chcemy przywrócić następujący ciąg "áe".Jak uzyskać odwrotny ciąg (bezpieczny dla Unicode)

Kod Unicode to "\ u0061 \ u0101 \ u0001".

Naiwny aproach od powrotu byłoby char przez char

private static String reverseStringNaive(String s) { 
    char[] characters = new char[s.length()]; 
    for (int i = s.length() - 1; i >= 0; i--) { 
     int j = s.length() - i - 1; 
     characters[j] = s.charAt(i); 
    } 
    return new String(characters); 
} 

który daje nam "EA" (\ u0065 \ u0301 \ u0061), kiedy mamy nadzieję dostać "EA" (\ u0065 \ u0061 \ u0301). Akcent akcentujący "" "należy trzymać razem z" a ", a nie z" e ".

Poniższy kod daje mi oczekiwany wynik dla tego łańcucha:

private static String reverseString(String s) { 
    char[] characters = new char[s.length()]; 
    for (int i = s.length() - 1; i >= 0; i--) { 
     int j = s.length() - i - 1; 
     if (Character.isLetterOrDigit(s.charAt(i)) || Character.isISOControl(s.charAt(i))) { 
      characters[j] = s.charAt(i); 
     } else { 
      characters[j] = s.charAt(i-1); 
      characters[j+1] = s.charAt(i); 
      i--; 
     } 
    } 
    return new String(characters); 
} 

mam sprawdzanie czy każdy znak jest literą, cyfrą lub ISO Control. Jeśli nie, zakładam, że powinna się trzymać z poprzednią postacią.

Pytanie brzmi, czy są inne rzeczy, które powinienem sprawdzić lub obawiać się? Czy mój aproach wciąż jest naiwny?

+0

Co powiesz na http://commons.apache.org/lang/api-2.5/org/apache/commons/lang/StringUtils.html#reverse(java.lang.String)? –

+0

To naiwne podejście. Daje zły wynik. – pablosaraiva

+0

Zgodnie z javadoc, używa 'StringBuffer.reverse()' i powinno to działać zobacz http://download.oracle.com/javase/1.5.0/docs/api/java/lang/StringBuffer.html#reverse () –

Odpowiedz

4

Twój problem można również rozwiązać, konwertując ciąg znaków do kanonicznej formy dekompozycji NFC. Zasadniczo, klasa java.text.Normalizer może być używana do łączenia akcentów i innych znaków łączących ze swoimi podstawowymi znakami, aby można było poprawnie odwrócić.

Wszystkie te inne pomysły (String.reverse(), StringBuffer.reverse()) będą poprawnie odwracały znaki w buforze, ale jeśli zaczniesz od rozłożonych znaków, możesz nie dostać tego, czego się spodziewasz :).

W niektórych "formach dekompozycji" znaki akcentowane są przechowywane oddzielnie od ich form podstawowych (jako oddzielne znaki), ale w "połączonej" formie nie są. Tak więc w jednej postaci "áe" jest przechowywane jako trzy znaki, a w drugiej, w postaci złożonej, jako dwie.

Jednak taka normalizacja nie jest wystarczająca do obsługi innych kombinacji znaków, ani nie może uwzględniać znaków w płaszczyznach astralnych Unicode, które są przechowywane jako dwie litery (lub więcej?) W Javie.

Dzięki tchristowi za wskazanie wsparcia ICU w zakresie segmentacji tekstu, w tym rozszerzonych klastrów grafem, takich jak ten opisany w komentarzach poniżej (patrz: wirama). This resource wydaje się być autorytatywnym źródłem informacji na ten temat.

+0

Działa, gdy korzystam z formularza NFC. – pablosaraiva

+0

I edytowane moją odpowiedź do pokazania NFC zamiast NFD –

+0

To jest rzeczywiście miły i aproach który działa dla wejścia ci dałem, ale nie udaje mu się następujący ciąg: सरस्वती. – pablosaraiva

Powiązane problemy