web-dev-qa-db-fra.com

Trier un tableau bidimensionnel basé sur une colonne

En Java, j'ai une donnée dans mon tableau comme la suivante

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

Je voudrais le trier en fonction de la première colonne, donc mes données finales peuvent ressembler à ceci

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 première colonne est une date au format "aaaa.MM.dj HH: mm" et la deuxième colonne est une chaîne.

40

Trier un tableau bidimensionnel basé sur une colonne
La première colonne est une date au format "aaaa.MM.dj HH: mm" et la deuxième colonne est une chaîne.

Puisque vous dites tableau 2D, je suppose que "date de format ..." signifie une chaîne. Voici le code pour trier un tableau 2D 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<String[]>() {
            @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]);
        }
    }

}

Sortie:

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
75
Bert F
class ArrayComparator implements Comparator<Comparable[]> {
    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 cette façon, vous pouvez gérer n'importe quel type de données dans ces tableaux (tant qu'ils sont comparables) et vous pouvez trier n'importe quelle colonne dans l'ordre croissant ou décroissant.

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

PS: assurez-vous de vérifier ArrayIndexOutOfBounds et autres.

EDIT: La solution ci-dessus ne serait utile que si vous êtes en mesure de stocker un Java.util.Date dans la première colonne ou si votre format de date vous permet d'utiliser une comparaison de chaîne simple pour ces valeurs . Sinon, vous devez convertir cette chaîne en une date, et vous pouvez y parvenir en utilisant une interface de rappel (comme solution générale). Voici une version améliorée:

class ArrayComparator implements Comparator<Object[]> {
    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);
        }
    }
}

Et à ce stade, vous pouvez trier sur votre première colonne avec:

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

J'ai ignoré les vérifications des valeurs nulles et autres problèmes de gestion des erreurs.

Je suis d'accord que cela commence déjà à ressembler à un framework.:)

Dernière édition (espérons-le): je me rends compte seulement maintenant que votre format de date vous permet d'utiliser une comparaison de chaîne simple. Si tel est le cas, vous n'avez pas besoin de la "version améliorée".

12
Costi Ciudatu
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]);
    }
});
8
Ron

En supposant que votre tableau contient des chaînes, vous pouvez utiliser ce qui suit:

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<String>() {
    @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 vous avez un tableau à deux dimensions, la solution est également très similaire:

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<String[]>() {
    @Override
    public int compare(String[] s1, String[] s2) {
        String t1 = s1[0];
        String t2 = s2[0];
        return t1.compareTo(t2);
    }
});
5
João Silva

Découvrez le ColumnComparator . Il s'agit essentiellement de la même solution que celle proposée par Costi, mais il prend également en charge le tri sur les colonnes d'une liste et possède quelques propriétés de tri supplémentaires.

3
camickr

Utilisation de Lambdas depuis 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));

Sortie:

[[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], [ 2009.07.25 20:01, Message F], [2009.07.25 20:17, Message G], [2009.07.25 19:54, Message R]]