Ordenar una matriz bidimensional basada en una columna

En Java, tengo una información en mi matriz como la siguiente

2009.07.25 20:24 Message A 2009.07.25 20:17 Message G 2009.07.25 20:25 Message B 2009.07.25 20:30 Message D 2009.07.25 20:01 Message F 2009.07.25 21:08 Message E 2009.07.25 19:54 Message R 

Me gustaría ordenarlo en base a la primera columna, por lo que mis datos finales pueden verse así

 2009.07.25 19:54 Message R 2009.07.25 20:01 Message F 2009.07.25 20:17 Message G 2009.07.25 20:24 Message A 2009.07.25 20:25 Message B 2009.07.25 20:30 Message D 2009.07.25 21:08 Message E 

La primera columna es una fecha de formato “aaaa.MM.dd HH: mm” y la segunda columna es una Cadena.

Ordenar una matriz bidimensional basada en una columna
La primera columna es una fecha de formato “aaaa.MM.dd HH: mm” y la segunda columna es una Cadena.

Como dices matriz bidimensional, supongo que “fecha de formato …” significa una cadena. Aquí hay un código para ordenar una matriz 2-D de String [] []:

 import java.util.Arrays; import java.util.Comparator; public class Asdf { public static void main(final String[] args) { final String[][] data = new String[][] { new String[] { "2009.07.25 20:24", "Message A" }, new String[] { "2009.07.25 20:17", "Message G" }, new String[] { "2009.07.25 20:25", "Message B" }, new String[] { "2009.07.25 20:30", "Message D" }, new String[] { "2009.07.25 20:01", "Message F" }, new String[] { "2009.07.25 21:08", "Message E" }, new String[] { "2009.07.25 19:54", "Message R" } }; Arrays.sort(data, new Comparator() { @Override public int compare(final String[] entry1, final String[] entry2) { final String time1 = entry1[0]; final String time2 = entry2[0]; return time1.compareTo(time2); } }); for (final String[] s : data) { System.out.println(s[0] + " " + s[1]); } } } 

Salida:

 2009.07.25 19:54 Message R 2009.07.25 20:01 Message F 2009.07.25 20:17 Message G 2009.07.25 20:24 Message A 2009.07.25 20:25 Message B 2009.07.25 20:30 Message D 2009.07.25 21:08 Message E 
 class ArrayComparator implements Comparator { private final int columnToSort; private final boolean ascending; public ArrayComparator(int columnToSort, boolean ascending) { this.columnToSort = columnToSort; this.ascending = ascending; } public int compare(Comparable[] c1, Comparable[] c2) { int cmp = c1[columnToSort].compareTo(c2[columnToSort]); return ascending ? cmp : -cmp; } } 

De esta forma puede manejar cualquier tipo de datos en esas matrices (siempre que sean Comparables) y puede ordenar cualquier columna en orden ascendente o descendente.

 String[][] data = getData(); Arrays.sort(data, new ArrayComparator(0, true)); 

PD: asegúrate de comprobar ArrayIndexOutOfBounds y otros.

EDITAR: la solución anterior solo sería útil si puede almacenar un java.util.Date en la primera columna o si su formato de fecha le permite usar la comparación de cadenas simples para esos valores . De lo contrario, debe convertir esa cadena en una fecha, y puede lograr eso usando una interfaz de callback (como una solución general). Aquí hay una versión mejorada:

 class ArrayComparator implements Comparator { private static Converter DEFAULT_CONVERTER = new Converter() { @Override public Comparable convert(Object o) { // simply assume the object is Comparable return (Comparable) o; } }; private final int columnToSort; private final boolean ascending; private final Converter converter; public ArrayComparator(int columnToSort, boolean ascending) { this(columnToSort, ascending, DEFAULT_CONVERTER); } public ArrayComparator(int columnToSort, boolean ascending, Converter converter) { this.columnToSort = columnToSort; this.ascending = ascending; this.converter = converter; } public int compare(Object[] o1, Object[] o2) { Comparable c1 = converter.convert(o1[columnToSort]); Comparable c2 = converter.convert(o2[columnToSort]); int cmp = c1.compareTo(c2); return ascending ? cmp : -cmp; } } interface Converter { Comparable convert(Object o); } class DateConverter implements Converter { private static final DateFormat df = new SimpleDateFormat("yyyy.MM.dd hh:mm"); @Override public Comparable convert(Object o) { try { return df.parse(o.toString()); } catch (ParseException e) { throw new IllegalArgumentException(e); } } } 

Y en este punto, puede ordenar su primera columna con:

 Arrays.sort(data, new ArrayComparator(0, true, new DateConverter()); 

Me salté los cheques por nulos y otros problemas de manejo de errores.

Estoy de acuerdo con que esto ya empieza a parecer un marco. 🙂

Última edición (con suerte): ahora me doy cuenta de que su formato de fecha le permite usar la comparación de cadena simple. Si ese es el caso, no necesita la “versión mejorada”.

 Arrays.sort(yourarray, new Comparator() { public int compare(Object o1, Object o2) { String[] elt1 = (String[])o1; String[] elt2 = (String[])o2; return elt1[0].compareTo(elt2[0]); } }); 

Suponiendo que su matriz contiene cadenas, puede usar lo siguiente:

 String[] data = new String[] { "2009.07.25 20:24 Message A", "2009.07.25 20:17 Message G", "2009.07.25 20:25 Message B", "2009.07.25 20:30 Message D", "2009.07.25 20:01 Message F", "2009.07.25 21:08 Message E", "2009.07.25 19:54 Message R" }; Arrays.sort(data, new Comparator() { @Override public int compare(String s1, String s2) { String t1 = s1.substring(0, 16); // date/time of s1 String t2 = s2.substring(0, 16); // date/time of s2 return t1.compareTo(t2); } }); 

Si tiene una matriz bidimensional, la solución también es muy similar:

 String[][] data = new String[][] { { "2009.07.25 20:17", "Message G" }, { "2009.07.25 20:25", "Message B" }, { "2009.07.25 20:30", "Message D" }, { "2009.07.25 20:01", "Message F" }, { "2009.07.25 21:08", "Message E" }, { "2009.07.25 19:54", "Message R" } }; Arrays.sort(data, new Comparator() { @Override public int compare(String[] s1, String[] s2) { String t1 = s1[0]; String t2 = s2[0]; return t1.compareTo(t2); } }); 
  1. instalar java8 jdk + jre

  2. Usa la expresión lamda para ordenar una matriz 2D .

código:

 import java.util.Arrays; import java.util.Comparator; class SortString { public static void main(final String[] args) { final String[][] data = new String[][] { new String[] { "2009.07.25 20:24", "Message A" }, new String[] { "2009.07.25 20:17", "Message G" }, new String[] { "2009.07.25 20:25", "Message B" }, new String[] { "2009.07.25 20:30", "Message D" }, new String[] { "2009.07.25 20:01", "Message F" }, new String[] { "2009.07.25 21:08", "Message E" }, new String[] { "2009.07.25 19:54", "Message R" } }; // this is applicable only in java 8 version. Arrays.sort(data, (String[] s1, String[] s2) -> s1[0].compareTo(s2[0])); // we can also use Comparator.comparing and point to Comparable value we want to use // Arrays.sort(data, Comparator.comparing(row->row[0])); for (final String[] s : data) { System.out.println(s[0] + " " + s[1]); } } } 

salida

 2009.07.25 19:54 Message R 2009.07.25 20:01 Message F 2009.07.25 20:17 Message G 2009.07.25 20:24 Message A 2009.07.25 20:25 Message B 2009.07.25 20:30 Message D 2009.07.25 21:08 Message E 

Mira el ColumnComparator . Básicamente es la misma solución propuesta por Costi, pero también admite la clasificación en columnas en una lista y tiene algunas propiedades de clasificación más.

Usando Lambdas desde java 8:

 final String[][] data = new String[][] { new String[] { "2009.07.25 20:24", "Message A" }, new String[] { "2009.07.25 20:17", "Message G" }, new String[] { "2009.07.25 20:25", "Message B" }, new String[] { "2009.07.25 20:30", "Message D" }, new String[] { "2009.07.25 20:01", "Message F" }, new String[] { "2009.07.25 21:08", "Message E" }, new String[] { "2009.07.25 19:54", "Message R" } }; String[][] out = Arrays.stream(data).sorted(Comparator.comparing(x -> x[1])).toArray(String[][]::new); System.out.println(Arrays.deepToString(out)); 

Salida:

[[2009.07.25 20:24, Mensaje A], [2009.07.25 20:25, Mensaje B], [2009.07.25 20:30, Mensaje D], [2009.07.25 21:08, Mensaje E], [ 2009.07.25 20:01, Mensaje F], [2009.07.25 20:17, Mensaje G], [2009.07.25 19:54, Mensaje R]]