Foros del Web » Programación para mayores de 30 ;) » Java »

[SOLUCIONADO] Ordenar ArrayList

Estas en el tema de Ordenar ArrayList en el foro de Java en Foros del Web. Hola Este es mi primer post, me pueden ayudar. Como puedo hacer para ordenar un ArrayList de contraseñas siguiendo este orden: - 1º las letras ...
  #1 (permalink)  
Antiguo 20/10/2014, 04:54
 
Fecha de Ingreso: marzo-2014
Mensajes: 9
Antigüedad: 10 años
Puntos: 0
Pregunta Ordenar ArrayList

Hola

Este es mi primer post, me pueden ayudar.

Como puedo hacer para ordenar un ArrayList de contraseñas siguiendo este orden:

- 1º las letras siguiendo el orden del alfabeto español,
- 2º los números del 0 al 9
- 3º símbolos especiales ordenados por su código en Unicode UTF-16 que es el orden utilizado en java internamente, menos el espacio en blanco.

Por ejemplo:

ArrayList con [password1, password2, pass, pass2,pass%,pass$]

Y la salida es:
pass password1 password2 pass2 pass$ pass%


Gracias por la ayuda.
  #2 (permalink)  
Antiguo 20/10/2014, 05:01
Avatar de Xerelo  
Fecha de Ingreso: mayo-2009
Mensajes: 2.175
Antigüedad: 14 años, 11 meses
Puntos: 306
Respuesta: Ordenar ArrayList

Teniendo en cuenta que esa List será de String, lo mejor que puedes hacer es crear un Comparator y llamar al método Collections.sort(List,Comparator)

http://docs.oracle.com/javase/6/docs...java.util.List, java.util.Comparator)

http://javaparanulos.blogspot.com.es...r-en-java.html
__________________
Cada vez que solucionas los problemas de alguien que no se esfuerza, piensa en que el día de mañana puede llegar a ser tu compañero de trabajo, o peor, tu jefe.
  #3 (permalink)  
Antiguo 20/10/2014, 13:08
 
Fecha de Ingreso: marzo-2014
Mensajes: 9
Antigüedad: 10 años
Puntos: 0
Respuesta: Ordenar ArrayList

Cita:
Iniciado por Xerelo Ver Mensaje
Teniendo en cuenta que esa List será de String, lo mejor que puedes hacer es crear un Comparator y llamar al método Collections.sort(List,Comparator)

[url]http://docs.oracle.com/javase/6/docs/api/java/util/Collections.html#sort(java.util.List[/url], java.util.Comparator)

[url]http://javaparanulos.blogspot.com.es/2012/02/comparator-en-java.html[/url]
Gracias lo estube mirando pero no me sirve, porque el valor de los numeros es mas pequeño que el de las letras y no los ordena como quiero.

Saludos.
  #4 (permalink)  
Antiguo 20/10/2014, 18:38
Avatar de Andreslrz  
Fecha de Ingreso: septiembre-2008
Mensajes: 99
Antigüedad: 15 años, 7 meses
Puntos: 2
Respuesta: Ordenar ArrayList

Pues segun veo lo que debes hacer es primero separar la contraseña por caracteres y determinar como piensas ordenar, ya que si una contraseña empieza con una letra y otra con un caracter especial no puedes comparar el ascii con el UTF-16, en ese caso deberias escoger que iria primero, si el caracter especial o la letra o un numero.

Ya despues que escojas eso, es facil, solo escoges por orden de tipo de caracter para agrupar y ordenas con un algoritmo de ordenamiento, puede ser un bubble sort o un merge sort, despues repites lo mismo para los caracteres en la segunda posicion y asi sucesivamente, no tengo un algoritmo claro pero doy almenos la idea general.
  #5 (permalink)  
Antiguo 20/10/2014, 20:54
Avatar de HackmanC  
Fecha de Ingreso: enero-2008
Ubicación: Guatemala
Mensajes: 1.817
Antigüedad: 16 años, 2 meses
Puntos: 260
Sonrisa Respuesta: Ordenar ArrayList

Hola,

Cita:
Iniciado por Xerelo Ver Mensaje
Teniendo en cuenta que esa List será de String, lo mejor que puedes hacer es crear un Comparator y llamar al método Collections.sort(List,Comparator) ...
Cita:
Iniciado por shenron66 Ver Mensaje
Gracias lo estube mirando pero no me sirve, porque el valor de los numeros es mas pequeño que el de las letras y no los ordena como quiero. ...
Me imagino que a lo que se refiere Xerelo es que tienes que implementar la interface Comparator, que por defecto al ser una interface, no define la implementación. En otras palabras, cual va primero lo defines tú. Y tu tienes que implementar la lógica, no basarte en la implementación básica de String.compareTo().

Posiblemente estás confundiendo Collections.sort(List) con Collections.sort(List, Comparator). Averigua como funciona la interface Comparator realmente.

Cita:
Iniciado por Andreslrz Ver Mensaje
Pues segun veo lo que debes hacer es primero separar la contraseña por caracteres y determinar como piensas ordenar, ya que si una contraseña empieza con una letra y otra con un caracter especial no puedes comparar el ascii con el UTF-16, en ese caso deberias escoger que iria primero, si el caracter especial o la letra o un numero. ...
Técnicamente, usando la interface Comparator no importa, es decir, Java usa Unicode internamente y nunca hace conversiones a ASCII u otra tabla de caracteres sino se especifica explícitamente. Así que todos los números, letras y caracteres definidos dentro de ASCII están dentro de Unicode, y como bien sabes cada uno de dichos glifos tiene un número asignado, un 'code point'.

Si comparo el caracter Unicode \u0001 (un caracter de control) con \u0041 (una letra), simplemente va a decir que el mayor es la letra puesto que su número es mas grande.

Para cambiar eso hay que implementar una interface Comparator<T> de tipo String que pase por cada letra del String y compare su valor con cada letra del otro String, haciendo los ajustes necesarios en la implementación para que los números vayan después de las letras (que no es la implementación normal de String.compareTo()).

Cita:
Iniciado por Andreslrz Ver Mensaje
Ya despues que escojas eso, es facil, solo escoges por orden de tipo de caracter para agrupar y ordenas con un algoritmo de ordenamiento, puede ser un bubble sort o un merge sort, despues repites lo mismo para los caracteres en la segunda posicion y asi sucesivamente, no tengo un algoritmo claro pero doy almenos la idea general.
El método estático sort() de la clase Collections tiene ya implementado el algoritmo más eficiente para ordenar cualquier colección. Lo único que tienes que hacer es insertarle la lógica de cual es mas grande y cual es mas pequeño con una interface Comparator.

Saludos,

Última edición por HackmanC; 20/10/2014 a las 21:00 Razón: agregar colección ...
  #6 (permalink)  
Antiguo 21/10/2014, 00:37
Avatar de Profesor_Falken  
Fecha de Ingreso: agosto-2014
Ubicación: Mountain View
Mensajes: 1.323
Antigüedad: 9 años, 8 meses
Puntos: 182
Respuesta: Ordenar ArrayList

Cita:
El método estático sort() de la clase Collections tiene ya implementado el algoritmo más eficiente para ordenar cualquier colección. Lo único que tienes que hacer es insertarle la lógica de cual es mas grande y cual es mas pequeño con una interface Comparator.
Solo por completar la excelente respuesta de HackmanC, comentar que el metodo sort de Java utiliza concretamente el algoritmo Dual-Pivot Quicksort de Vladimir Yaroslavskiy.

Aqui teneis la especificacion de dicho algoritmo:
http://iaroslavski.narod.ru/quicksor...tQuicksort.pdf

Dicho algoritmo se comporta muy bien en la mayoria de los casos (O(nLogn)) aunque siempre hay situaciones limite en las que otros metodos de ordenacion pueden ser algo mas rapidos (por ejemplo, si la lista ya esta ordenada).


Un saludo
__________________
If to err is human, then programmers are the most human of us

Última edición por Profesor_Falken; 21/10/2014 a las 00:45
  #7 (permalink)  
Antiguo 21/10/2014, 03:22
 
Fecha de Ingreso: marzo-2014
Mensajes: 9
Antigüedad: 10 años
Puntos: 0
Respuesta: Ordenar ArrayList

Gracias a todos por las respuestas
  #8 (permalink)  
Antiguo 21/10/2014, 05:04
 
Fecha de Ingreso: marzo-2014
Mensajes: 9
Antigüedad: 10 años
Puntos: 0
Respuesta: Ordenar ArrayList

Cita:
Iniciado por HackmanC Ver Mensaje
Hola,

Para cambiar eso hay que implementar una interface Comparator<T> de tipo String que pase por cada letra del String y compare su valor con cada letra del otro String, haciendo los ajustes necesarios en la implementación para que los números vayan después de las letras (que no es la implementación normal de String.compareTo()).


El método estático sort() de la clase Collections tiene ya implementado el algoritmo más eficiente para ordenar cualquier colección. Lo único que tienes que hacer es insertarle la lógica de cual es mas grande y cual es mas pequeño con una interface Comparator.
Hola de nuevo

Estube mirando documentacion de comparator como en este enlace:

http://www.aprenderaprogramar.es/index.php?option=com_attachments&task=download&id= 541

Intente hacer el codigo pero no se como implementarlo:

http://pastebin.com/SV9cyB8K

Me pueden ayudar porfavor. Gracias
  #9 (permalink)  
Antiguo 21/10/2014, 05:59
Avatar de Xerelo  
Fecha de Ingreso: mayo-2009
Mensajes: 2.175
Antigüedad: 14 años, 11 meses
Puntos: 306
Respuesta: Ordenar ArrayList

Primero compruebas qué contraseña tiene menor tamaño.

Haces un sólo bucle for hasta el número del tamaño del password menor (evitas outbounds)

Dentro de ese bucle, comparas la posición que marca el índice del for en los dos password. Si son iguales las letras (aquí dependerá de cómo consideres mayúsculas y minúsculas) continuas el bucle. Recuerda que String se compara con equals, no con ==

Si no son iguales, llamas a un método que compara dos letras, que te devuelve cual es mayor y te sales del bucle.

En el método de comparar:

Ver de qué tipo son las letras, si son de distinto tipo, ya sabes cuál es mayor.

Si coinciden, comparas el valor en char (no sé si para los símbolos especiales te vale) o el codepoint
__________________
Cada vez que solucionas los problemas de alguien que no se esfuerza, piensa en que el día de mañana puede llegar a ser tu compañero de trabajo, o peor, tu jefe.
  #10 (permalink)  
Antiguo 21/10/2014, 06:02
Avatar de Profesor_Falken  
Fecha de Ingreso: agosto-2014
Ubicación: Mountain View
Mensajes: 1.323
Antigüedad: 9 años, 8 meses
Puntos: 182
Respuesta: Ordenar ArrayList

Es que hay que currase un poco el comparador.

Aqui te pongo uno sobre tu codigo. No lo he probado y lo mismo ni compila (lo he hecho en el notepad) pero te puede dar una idea



Código Java:
Ver original
  1. public class Prueba {
  2.  
  3.     public static void main(String[] args) {
  4.         // TODO Auto-generated method stub
  5.         List<String> lista = new ArrayList<>();
  6.  
  7.         //solo letras minusculas
  8.         lista.add("12a");
  9.         lista.add("acd");
  10.         lista.add("a%c");
  11.         lista.add("bdc");
  12.         lista.add("bc");//las contrasenas no tienen que ser del mismo tamano
  13.  
  14.         Collections.sort(lista, new Ordenar());
  15.  
  16.         System.out.print(lista);
  17.     }
  18. }
  19.  
  20. class Ordenar implements Comparator<String> {
  21.  
  22.     @Override
  23.     public int compare(String o1, String o2) {
  24.         if (o1 == null && o2 == null) {
  25.             return 0;
  26.         } else if (o2 == null) {
  27.             return -1;
  28.         } else if (o1 == null) {
  29.             return 1;
  30.         }
  31.        
  32.         //Select shortest to pivot on
  33.         int shortest = (o1.length() <= o2.length()) ? o1.length() : o2.length();
  34.  
  35.         for (int i = 0; i < shortest; i++) {
  36.             char charO1 = o1.charAt(i);
  37.             char charO2 = o2.charAt(i);
  38.  
  39.             if (Character.isLetter(charO1)) {
  40.                 if (!Character.isLetter(charO2)) {
  41.                     return -1;
  42.                 } else {
  43.                     int comp = Character.compare(charO1, charO2);
  44.                     if (comp != 0) {
  45.                         return comp;
  46.                     }
  47.                 }
  48.             } else if (Character.isDigit(charO1)) {
  49.                 if (Character.isLetter(charO2)) {
  50.                     return 1;
  51.                 } else if (Character.isDigit(charO2)) {
  52.                     int comp = Character.compare(charO1, charO2);
  53.                     if (comp != 0) {
  54.                         return comp;
  55.                     }
  56.                 } else {
  57.                     return -1;
  58.                 }
  59.             } else {
  60.                 if (Character.isLetter(charO2) || Character.isDigit(charO2)) {
  61.                     return 1;                    
  62.                 } else {
  63.                     int comp = Character.compare(charO1, charO2);
  64.                     if (comp != 0) {
  65.                         return comp;
  66.                     }
  67.                 }
  68.             }
  69.         }
  70.  
  71.         return (o1.length() <= o2.length()) ? -1 : 1;
  72.     }
  73. }


Un saludo
__________________
If to err is human, then programmers are the most human of us
  #11 (permalink)  
Antiguo 21/10/2014, 09:39
 
Fecha de Ingreso: marzo-2014
Mensajes: 9
Antigüedad: 10 años
Puntos: 0
Respuesta: Ordenar ArrayList

Gracias a los dos.

Probe tu codigo Profesor_Falken y compila bien.
Lo entiendo poco y entiendo poco de esto porque soy novato

el codigo esta bien para:

password1,password2,pass,pass2

ya que la salida es : pass,password1,password2,pass2

pero creo que esta mal para: 12a, acd, a%c, bdc, bc
la salida es : acd, a%c, bc, bdc, 12a

Saludos y gracias
  #12 (permalink)  
Antiguo 21/10/2014, 10:05
 
Fecha de Ingreso: marzo-2014
Mensajes: 9
Antigüedad: 10 años
Puntos: 0
Respuesta: Ordenar ArrayList

Cita:
Iniciado por shenron66 Ver Mensaje
Gracias a los dos.

pero creo que esta mal para: 12a, acd, a%c, bdc, bc
la salida es : acd, a%c, bc, bdc, 12a

Saludos y gracias
Me confundi, esta bien para ese caso.

Voy a intentar entenderlo.

Muchas gracias Profesor_Falken , eres el amo de Java, algún día quiero ser como tu de bueno
  #13 (permalink)  
Antiguo 21/10/2014, 11:56
Avatar de HackmanC  
Fecha de Ingreso: enero-2008
Ubicación: Guatemala
Mensajes: 1.817
Antigüedad: 16 años, 2 meses
Puntos: 260
Sonrisa Respuesta: Ordenar ArrayList

Hola,

Cita:
Iniciado por Profesor_Falken Ver Mensaje
Es que hay que currase un poco el comparador.
Ciertamente, y agregando mi versión del mismo, aunque no estoy seguro que de exactamente los mismo resultados, posiblemente sea mas simple de darle mantenimiento. Ahora solo queda observar el caso de la Ñ/ñ, CH/ch y otros casos especiales.

Código Java:
Ver original
  1. import java.util.Comparator;
  2.  
  3. public class Ordenar implements Comparator<String> {
  4.  
  5.     private int compare(char c1, char c2) {
  6.         int i1 = Character.isLetter(c1) ? 2 : Character.isDigit(c1) ? 1 : 0;
  7.         int i2 = Character.isLetter(c2) ? 2 : Character.isDigit(c2) ? 1 : 0;
  8.  
  9.         if (i1 != i2) {
  10.             return i2 - i1;
  11.         }
  12.  
  13.         return Character.compare(c1, c2);
  14.     }
  15.  
  16.     @Override
  17.     public int compare(String o1, String o2) {
  18.         if (o2.length() != o1.length()) {
  19.             return o1.length() - o2.length();
  20.         }
  21.  
  22.         int length = o1.length();
  23.         int compare;
  24.         for (int i = 0; i < length; i++) {
  25.             compare = compare(o1.charAt(i), o2.charAt(i));
  26.             if (compare != 0) {
  27.                 return compare;
  28.             }
  29.         }
  30.  
  31.         return 0;
  32.     }
  33.  
  34. }

Cita:
Iniciado por Profesor_Falken Ver Mensaje
... comentar que el metodo sort de Java utiliza concretamente el algoritmo Dual-Pivot Quicksort de Vladimir Yaroslavskiy. ...
De eso no puedo estar completamente seguro, pero según la documentación de Oracle, usa el método 'merge sort' ligeramente optimizado. Lo único que sé es que es rápido y estable.

http://docs.oracle.com/javase/tutori...hms/index.html

Saludos,
  #14 (permalink)  
Antiguo 21/10/2014, 12:27
Avatar de Profesor_Falken  
Fecha de Ingreso: agosto-2014
Ubicación: Mountain View
Mensajes: 1.323
Antigüedad: 9 años, 8 meses
Puntos: 182
Respuesta: Ordenar ArrayList

Buenas,

Está muy bien y es más DRY, solo le veo dos pegas de funcionamiento:
-Si un elemento de la lista es null explota con un NullPointerException.
-Da prioridad a las palabras con menos letras, que no es lo que se busca.

Por ejemplo, con la lista del ejemplo de este post devuelve esta ordenación:
[bc, acd, a%c, bdc, 12a]

Cuando debería devolver ésta:
acd, a%c, bc, bdc, 12a

Para arreglarlo basta con desplazar el if de la longitud después del bucle.

Código Java:
Ver original
  1. @Override
  2.     public int compare(String o1, String o2) {
  3.         int length = o1.length();
  4.         int compare;
  5.         for (int i = 0; i < length; i++) {
  6.             compare = compare(o1.charAt(i), o2.charAt(i));
  7.             if (compare != 0) {
  8.                 return compare;
  9.             }
  10.         }
  11.        if (o2.length() != length) {
  12.             return length - o2.length();
  13.         }
  14.  
  15.         return 0;
  16.     }


Un saludo
__________________
If to err is human, then programmers are the most human of us
  #15 (permalink)  
Antiguo 21/10/2014, 12:54
Avatar de HackmanC  
Fecha de Ingreso: enero-2008
Ubicación: Guatemala
Mensajes: 1.817
Antigüedad: 16 años, 2 meses
Puntos: 260
Sonrisa Respuesta: Ordenar ArrayList

Hola,

Tienes toda la razón, solo un par de comentarios adicionales con el afán de compartir nada mas,

Cita:
Iniciado por Profesor_Falken Ver Mensaje
...
-Si un elemento de la lista es null explota con un NullPointerException.
La especificación de Objects.compare(T o1, T o2, Comparator<T>), así lo define, si uno es null 'posiblemente' tire un NullPointerException. No digo que no se pueda corregir o no sea buena observación, simplemente que la interface Comparator no define eso.

Sería aconsejable validar los nulos al principio con el código que propusiste.

Cita:
Iniciado por Profesor_Falken Ver Mensaje
...
-Da prioridad a las palabras con menos letras, que no es lo que se busca.
Tienes toda la razón en eso también, ya será cosa de shenron66 modificarlo a sus requerimientos correctamente, que adicionalmente indicaba que necesitaba el ordenamiento en Español, eso incluye la Ñ en la posición correcta, y no lo implementé tampoco. Solo es para que se dé una idea de como hacerlo.

Cita:
Iniciado por Profesor_Falken Ver Mensaje
...
Para arreglarlo basta con desplazar el if de la longitud después del bucle.
...
Creo que la corrección sería mas compleja que eso, porque en el ciclo, si no son de la misma longitud posiblemente tiraría una excepción. Pero es muy buena observación y tendrá que modificarlo shenron66 consecuentemente.

Saludos,

Última edición por HackmanC; 21/10/2014 a las 12:58 Razón: depues del bucle
  #16 (permalink)  
Antiguo 21/10/2014, 13:35
 
Fecha de Ingreso: marzo-2014
Mensajes: 9
Antigüedad: 10 años
Puntos: 0
Respuesta: Ordenar ArrayList

Gracias HackmanC y Profesor_Falken.

Este foro es genial, Salu2 .
  #17 (permalink)  
Antiguo 23/10/2014, 13:41
 
Fecha de Ingreso: marzo-2014
Mensajes: 9
Antigüedad: 10 años
Puntos: 0
Respuesta: Ordenar ArrayList

Hola

Solo una cosa mas Profesor_Falken como puedo implementar la ñ para que vaya despues de la n y antes de la o . Lo estube mirando y no hay forma de que me salga.

saludos
  #18 (permalink)  
Antiguo 24/10/2014, 12:45
Avatar de Profesor_Falken  
Fecha de Ingreso: agosto-2014
Ubicación: Mountain View
Mensajes: 1.323
Antigüedad: 9 años, 8 meses
Puntos: 182
Respuesta: Ordenar ArrayList

Ya, y también tendrás el mismo problema con los acentos.

Utilizando una complementación de Collator (clase añadida con Java 5 y una de las grandes olvidadas de Java), puede realizar comparaciones de lenguaje natural fácilmente. Solo debes cambiar dos lineas.

1- Crear un collator utilizando el locale que nos interese, en este caso el español:
Collator collator = Collator.getInstance(new Locale("es", "ES"));


2- Luego cuando haces la comparacion de letras, puedes usar el collator para comparar. Collator trabaja con Strings, por lo que podemos hacer una conversion:
int comp = collator.compare(String.valueOf(charO1), String.valueOf(charO2));

Esto aplicaría tanto para el código que te puse como para el de HackmanC

Por ejemplo, partiendo de mi código inicial:

Código Java:
Ver original
  1. public class Prueba {
  2.  
  3.     public static void main(String[] args) {
  4.         // TODO Auto-generated method stub
  5.         List<String> lista = new ArrayList<>();
  6.  
  7.         //solo letras minusculas
  8.         lista.add("12a");
  9.         lista.add("acd");
  10.         lista.add("and");
  11.         lista.add("aod");        
  12.         lista.add("a%c");        
  13.         lista.add("a0d");
  14.         lista.add("aád");
  15.         lista.add("bdc");
  16.         lista.add("añd");
  17.         lista.add("bc"); //las contrasenas no tienen que ser del mismo tamano
  18.  
  19.         Collections.sort(lista, new Ordenar());
  20.  
  21.         System.out.print(lista);
  22.     }
  23. }
  24.  
  25. class Ordenar implements Comparator<String> {
  26.  
  27.     @Override
  28.     public int compare(String o1, String o2) {
  29.         if (o1 == null && o2 == null) {
  30.             return 0;
  31.         } else if (o2 == null) {
  32.             return -1;
  33.         } else if (o1 == null) {
  34.             return 1;
  35.         }
  36.         Collator collator = Collator.getInstance(new Locale("es", "ES"));
  37.  
  38.         //Select shortest to pivot on
  39.         int shortest = (o1.length() <= o2.length()) ? o1.length() : o2.length();
  40.  
  41.         for (int i = 0; i < shortest; i++) {
  42.             char charO1 = o1.charAt(i);
  43.             char charO2 = o2.charAt(i);
  44.  
  45.             if (Character.isLetter(charO1)) {
  46.                 if (!Character.isLetter(charO2)) {
  47.                     return -1;
  48.                 } else {
  49.                     int comp = collator.compare(String.valueOf(charO1), String.valueOf(charO2));
  50.                     if (comp != 0) {
  51.                         return comp;
  52.                     }
  53.                 }
  54.             } else if (Character.isDigit(charO1)) {
  55.                 if (Character.isLetter(charO2)) {
  56.                     return 1;
  57.                 } else if (Character.isDigit(charO2)) {
  58.                     int comp = collator.compare(charO1, charO2);
  59.                     if (comp != 0) {
  60.                         return comp;
  61.                     }
  62.                 } else {
  63.                     return -1;
  64.                 }
  65.             } else {
  66.                 if (Character.isLetter(charO2) || Character.isDigit(charO2)) {
  67.                     return 1;
  68.                 } else {
  69.                     int comp = collator.compare(charO1, charO2);
  70.                     if (comp != 0) {
  71.                         return comp;
  72.                     }
  73.                 }
  74.             }
  75.         }
  76.  
  77.         return (o1.length() <= o2.length()) ? -1 : 1;
  78.     }
  79. }

Resultado: [aád, acd, and, añd, aod, a0d, a%c, bc, bdc, 12a]

Un saludo
__________________
If to err is human, then programmers are the most human of us

Etiquetas: arraylist
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 02:32.