2011-09-19 9 views
18

Supongamos que queremos revertir la siguiente Cadena "áe".Cómo obtener una Cadena invertida (caja fuerte Unicode)

El unicode para eso es "\ u0061 \ u0301 \ u0065".

El abordaje ingenua de revertir sería charla por 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); 
} 

que nos da "EA" (\ u0065 \ u0301 \ u0061) cuando esperamos conseguir "EA" (\ u0065 \ u0061 \ u0301). El acento agudo "'" debe permanecer junto con la "a", no cambiar a la "e".

El siguiente código me da el resultado esperado para esa cadena:

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

estoy comprobando si cada carácter es letra, dígito o Control ISO. Si no, supongo que debe permanecer junto con el personaje anterior.

La pregunta es, ¿hay otras cosas que deba consultar o preocuparse? ¿Mi enfoque sigue siendo ingenuo?

+0

¿Qué hay de http://commons.apache.org/lang/api-2.5/org/apache/commons/lang/StringUtils.html#reverse(java.lang.String)? –

+0

Hace el enfoque ingenuo. Da el resultado incorrecto – pablosaraiva

+0

De acuerdo con javadoc, usa un 'StringBuffer.reverse()' y esto debería funcionar, vea http://download.oracle.com/javase/1.5.0/docs/api/java/lang/StringBuffer.html#reverse () –

Respuesta

4

Su problema también podría resolverse convirtiendo la cadena en la forma de descomposición canónica NFC. Básicamente, la clase java.text.Normalizer se puede usar para combinar acentos y otros caracteres combinados con sus caracteres base para que pueda revertir correctamente.

Todas estas otras ideas (String.reverse(), StringBuffer.reverse()) invertirán correctamente los caracteres en su búfer, pero si comienza con caracteres descompuestos, es posible que no obtenga lo que espera :).

En algunas "formas de descomposición", los caracteres de acento se almacenan separados de sus formas base (como caracteres separados), pero en la forma "combinada" no lo son. Entonces, en una forma "áe" se almacena como tres caracteres, y en la otra, forma combinada, como dos.

Sin embargo, dicha normalización no es suficiente para manejar otros tipos de combinación de caracteres, ni puede representar caracteres en los planos astrales Unicode, que se almacenan como dos caracteres (o más?) En Java.

Gracias a tchrist por señalar la compatibilidad de la ICU para la segmentación de texto, incluidos los clústeres de grafemas extendidos, como el identificado en los comentarios a continuación (ver virama). This resource parece ser la fuente autorizada de información sobre este tipo de cosas.

+0

Funciona si cuando utilicé el formulario NFC. – pablosaraiva

+0

Edité mi respuesta para mostrar NFC en lugar de NFD –

+0

De hecho, es un buen enfoque que funciona para la entrada que te di, pero falla en la siguiente cadena: सरस्वती. – pablosaraiva

Cuestiones relacionadas