2011-09-19 13 views
18

Supponiamo di voler ripristinare la seguente stringa "áe".Come ottenere una stringa inversa (unicode safe)

L'unicode per questo è "\ u0061 \ u0101 \ u0065".

L'aproach ingenua di un ritorno sarebbe char da 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); 
} 

che ci dà "EA" (\ u0065 \ u0301 \ u0061), quando speriamo di ottenere "EA" (\ u0065 \ u0061 \ u0301). L'accuto d'accento "'" dovrebbe rimanere unito alla "a", non cambiare alla "e".

Il seguente codice mi dà il risultato atteso per quella stringa:

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); 
} 

Sto controllando se ogni personaggio è lettera, numero o ISO Control. In caso contrario, presumo che dovrebbe restare unito al personaggio precedente.

La domanda è: ci sono altre cose da controllare o preoccupare? Il mio aproach è ancora ingenuo?

+0

E a proposito di http://commons.apache.org/lang/api-2.5/org/apache/commons/lang/StringUtils.html#reverse(java.lang.String)? –

+0

Fa l'apioach ingenuo. Dà il risultato sbagliato – pablosaraiva

+0

Secondo javadoc, usa un 'StringBuffer.reverse()' e questo dovrebbe funzionare vedere http://download.oracle.com/javase/1.5.0/docs/api/java/lang/StringBuffer.html#reverse () –

risposta

4

Il problema può essere risolto convertendo la stringa nel modulo di decomposizione canonico NFC. Fondamentalmente, la classe java.text.Normalizer può essere utilizzata per combinare accenti e altri caratteri combinati con i loro caratteri di base in modo da essere in grado di invertire correttamente.

Tutte queste altre idee (String.reverse(), StringBuffer.reverse()) invertiranno correttamente i caratteri nel buffer, ma se inizi con caratteri scomposti, potresti non ottenere ciò che ti aspetti :).

In alcune "forme di scomposizione", i caratteri di accento sono memorizzati separatamente dalle loro forme di base (come caratteri separati), ma in forma "combinata" non lo sono. Quindi in una forma "áe" è memorizzato come tre caratteri, e nell'altra, nella forma combinata, come due.

Tuttavia, tale normalizzazione non è sufficiente per gestire altri tipi di combinazione di caratteri, né può rappresentare i caratteri nei piani astrali Unicode, che sono memorizzati come due caratteri (o più?) In Java.

Grazie a tchrist per aver segnalato il supporto della ICU per la segmentazione del testo, inclusi cluster di grafema estesi come quello identificato nei commenti sotto (vedere virama). This resource sembra essere la fonte autorevole di informazioni su questo genere di cose.

+0

Funziona se quando ho usato il modulo NFC. – pablosaraiva

+0

Ho modificato la mia risposta per mostrare NFC piuttosto che NFD –

+0

È davvero un bell'aproach che funziona per l'input che ti ho dato, ma non riesce alla seguente stringa: सरस्वती. – pablosaraiva

Problemi correlati