2010-11-17 16 views
6

Estoy tratando de ordenar una Lista de objetos por el campo de cadena "país". Cada país está en su lengua maternaOrdenando múltiples cadenas locales en Java

  • Argentina
  • Australia
  • Österreich
  • Ελλάδα
  • България ...

Lo que quiero hacer es conseguir "България" por ejemplo, aparecer después de los países "A *", ya que la letra 'Б' corresponde a la latina 'B'. Intento utilizar el Collater predeterminado, pero los nombres que no son latinos aún terminan en la lista por última vez.

Aquí está mi código hasta ahora:

private static final Comparator<DomainTO> DOMAIN_COUNTRY_COMPARATOR = 
    new Comparator<DomainTO>() { 
    @Override 
    public int compare(DomainTO t, DomainTO t1) { 
     Collator defaultCollator = Collator.getInstance(); 
     return defaultCollator.compare(t.getCountry(), t1.getCountry()); 
    } 
}; 
+0

Me gustaría dejar de definir mis propias reglas de Clasificador si es posible. – cbaby

Respuesta

32

cómo ordenar las palabras de diferentes idiomas? Hay muchos alfabetos (inglés, ruso, alemán, etc.). Todos tienen lista de letras ordenada. Es fácil ordenar las palabras que provienen de un alfabeto. ¿Pero es posible fusionar todos estos alfabetos en uno?
Creo que no es posible hacerlo de una manera que todos puedan aceptar. Como ejemplo, tome alfabetos en inglés y ruso. Las letras rusas se pueden convertir a letras inglesas (al menos la mayoría de ellas) pero después de este casting cambiarían el orden. Esto estaría favoreciendo un alfabeto sobre otro. ¿Por qué no enviar cartas en inglés al ruso?
Otro problema es que hay letras especiales. En alemán hay Ö entre O y P y en polaco hay Ó en este lugar. Así hemos siguientes relaciones:

O < Ö < P 
O < Ó < P 

Pero ¿cuál es la relación entre O y O? Si hubiera un país Ósterreich ¿debería ser antes o después de Österreich? Por lo tanto, es imposible definir reglas universales para clasificar palabras de diferentes idiomas.

Todo lo que podemos hacer es lanzar todos los alfabetos a la elegida. Y esto es lo que OP está tratando de hacer.
El elegido es el alfabeto latino y otros alfabetos tienen que ser convertidos a este. El problema es que este casting suele ser ambiguo. Fácilmente solo podemos lanzar la mayoría de las letras rusas o griegas.
Problema mucho más grande es con los idiomas árabes o asiáticos. Y deberíamos recordar que cuando lanzamos de un alfabeto a otro a menudo perdemos algo.

Entonces, ¿cómo podemos hacer tal clasificación?

  1. La primera proposición es proporcionar manualmente el nombre latino para cada país.Así tendríamos una lista que contiene pares como
    • Россия Rossija
    • Ελλάδα Ellada
      Entonces podríamos ordenar por nombre y mostrar nombres latinos.
  2. segundo enfoque se está ejecutando código similar al siguiente:

Código:

char [] russian = "АаБбВвГгДдЕеЁёЖжЗзИиЙйКкЛлМмНнОоПпРрСсТтУуФфХхЦцЧчШшЩщ".toCharArray(); 
char [] russian_to = "AaBbWwGgDdEeEeZzZzIiJjKkLlMmNnOoPpRrSsTtUuFfHhCcCcSsss".toCharArray(); 
for (int i = 0; i < russian.length; i++) { 
    input = input.replace(russian[i], russian_to[i]); 
} 

De esta manera convertimos todas las letras del alfabeto ruso. Ahora tenemos que agregar un código similar para otros alfabetos. Y el ruso fue el más simple.
Pero supongamos que lo logramos y logramos clasificar palabras de todos los idiomas del mundo.
Pero, ¿cuáles son las consecuencias de realizar dicha clasificación? Antes de responder a esta pregunta, preguntemos cuáles fueron las intenciones de hacer esto. OP no dijo sus razones para hacer dicha clasificación. Pero podemos deducirlo:

  • ¿Por qué ordenamos los elementos ?: Para que sean más fáciles de encontrar.
  • ¿Por qué los nombres de los países están en idiomas maternos ?: Para que esta lista sea útil para aquellos ciudadanos del mundo que solo conocen el idioma nativo.

Respondamos la pregunta: ¿Esta clasificación hace que sea más fácil encontrar un país específico para un hombre que solo conoce su lengua materna?

  1. Si alguien es de Austria luego se supone que Österreich será después de todos los países que empiezan con O. Pero después de la normalización será Österreich Österreich y será en algún lugar entre Ontario y Ottawa. (Sé que Ontario y Ottawa no son países. Es solo un ejemplo).
  2. Si alguien es de Japón y no sabe el alfabeto latino, esta clasificación sería inútil para él. Tendría que escanear toda la lista hasta que encuentre su país.
  3. Supongamos que hay un país Волгоград (Wolgograd) y hay un ciudadano de este país que solo sabe el alfabeto ruso. En el alfabeto ruso, В es la tercera letra, por lo que este hombre buscaría al principio de la lista (en algún lugar entre Belgia y Danmark) cuando Волгоград estaría cerca del final de la lista (cerca de Venezuela). , por lo tanto, en este caso, la clasificación no solo no será útil, sino también engañosa.
  4. Si alguien sabe el alfabeto latino y está buscando su país, entonces esto no puede ser fácil. Cuando todos los países llevan el nombre en inglés y estoy buscando 'Polonia', siempre sé si debo subir o bajar de la lista. Si veo 'Japón' sé que pasaré a la lista. Cuando veo 'Rusia', entonces sé subir.
    Pero si lo hiciéramos ordenando para todos estos nombres, entonces podría haber un problema. Si veo ايران, entonces no podré decidir si subir o bajar la lista. Por lo tanto, en este ejemplo, la clasificación no es útil. Peor escenario es cuando encuentro a Волгоград en la lista. No sé el alfabeto ruso y supongo que estoy cerca de la letra 'B' cuando, de hecho, estoy cerca del final de la lista. Entonces elegiría la dirección incorrecta.

Resumen:

Ordenación de nombres de países escritos en diferentes idiomas es difícil de definir y poner en práctica. Y cuando se implemente, no sería útil o perjudicial.

2

tal vez usted puede comparar las cadenas normalizadas. Algo como esto:

private static final Comparator<DomainTO> DOMAIN_COUNTRY_COMPARATOR = 
    new Comparator<DomainTO>() { 

     private String normalize(final String input) { 
      return Normalizer 
       .normalize(input, Normalizer.Form.NFD) 
       .replaceAll("[^\\p{ASCII}]", ""); 
     } 

     @Override 
     public int compare(final DomainTO t, final DomainTO t1) { 
      return normalize(t.getCountry()).compareTo(
       normalize(t1.getCountry())); 
     } 
    }; 

ver pregunta relacionada acerca de la normalización: Converting Java String to ascii (esta cuestión está vinculada a varias preguntas similares)

+0

No, la normalización de cadenas no latinas devuelve una cadena vacía, por lo que ahora terminan primero. – cbaby

+2

Bien, aún dejo la respuesta para que otros sepan que no es la respuesta correcta. –