43 votes

Trier un tableau à deux dimensions en fonction d'une seule colonne

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

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 les trier sur la base de la première colonne, de sorte que mes données finales puissent 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 "yyyy.MM.dd HH:mm" et la deuxième colonne est une chaîne de caractères.

81voto

Bert F Points 27237

Trier un tableau à deux dimensions en fonction d'une seule colonne
La première colonne est une date au format "yyyy.MM.dd HH:mm" et la deuxième colonne est une chaîne de caractères.

Puisque vous dites tableau 2-D, je suppose que "date du format ..." signifie un String. Voici le code pour trier un tableau 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<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

2 votes

Simple ! J'ai essayé et cela a fonctionné comme prévu - merci - en marquant comme réponse correcte

0 votes

@emaillenin - Je suis heureux d'avoir pu aider.

0 votes

@BertF, utile. Si je veux comparer dans l'ordre naturel, que dois-je faire ? Et +1 pour la bonne réponse :)

12voto

Costi Ciudatu Points 13020
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 manipuler 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 réellement un java.util.Date dans la première colonne ou si votre format de date vous permet d'utiliser une simple comparaison de chaînes de caractères pour ces valeurs. . Sinon, vous devez convertir cette chaîne en une date, et vous pouvez le faire 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 nuls et autres problèmes de gestion des erreurs.

Je suis d'accord pour dire que cela commence déjà à ressembler à un cadre :)

Dernière modification (si tout va bien) : je réalise seulement maintenant que votre format de date vous permet d'utiliser une simple comparaison de chaînes. Si c'est le cas, vous n'avez pas besoin de la "version améliorée".

1 votes

+1, pour la solution plus générale permettant de trier par n'importe quel objet et sur n'importe quelle colonne.

0 votes

C'est une bonne solution générale, mais la question telle qu'elle est posée demande le tri d'une String[] où chaque String contient des données en colonnes. Le titre ne correspond pas à la question ; cette réponse ne satisfait que le titre...

8voto

Ron Points 1149
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]);
    }
});

5voto

João Silva Points 36619

En supposant que votre tableau contient des chaînes de caractères, 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);
    }
});

0 votes

@dogbane Jetez un coup d'oeil à la question. C'est no est en fait un tableau 2D, même si le titre insiste sur ce point. Il s'agit d'un tableau de String avec des données en colonne à l'intérieur. En fait, cette réponse répond mieux que toutes les autres à la question posée...

1 votes

@dkarp pourquoi comparez-vous seulement les heures ? Vous devriez comparer la première colonne qui est "yyyy.MM.dd HH:mm". Regardez à nouveau la question.

0 votes

@dogbane Oh, c'est un bon point. (Pas ma réponse, cependant.) Tout de même, un bon réponse à cette question doit la traiter comme un String[] avec des données en colonnes dans le format décrit par le PO, et non pas comme une String[][] . Je l'aurais dé-upvoté si j'avais vu votre commentaire plus tôt, cependant...

3voto

camickr Points 137095

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X