Sortarea unei matrice bidimensionale pe baza unei coloane (Programare, Java, Array-Uri, Sortare)

Lenin Raj Rajasekaran a intrebat.

În Java, am o serie de date în matricea mea, după cum urmează

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

Aș dori să le sortez pe baza primei coloane, astfel încât datele mele finale să arate astfel

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

Prima coloană este o dată cu formatul „aaaa.MM.dd HH:mm”, iar a doua coloană este un șir de caractere.

8 răspunsuri
Bert F

Sortarea unui array bidimensional pe baza unei coloane
Prima coloană este o dată cu formatul „yyyy.MM.dd HH:mm”, iar a doua coloană este un String.

Din moment ce spuneți array bidimensional, presupun că „data de format …” înseamnă un String. Iată codul pentru sortarea unui array 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]);
        }
    }

}

Output:

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

Comentarii

  • simplu! L-am încercat și a funcționat conform așteptărilor – mulțumesc – marcând ca răspuns corect –  > Por Lenin Raj Rajasekaran.
  • @emaillenin – Mă bucur că am putut ajuta -.  > Por Bert F.
  • @BertF, De ajutor. Dacă vreau să compar în ordine naturală, ce ar trebui să fac? Și +1 pentru răspuns frumos 🙂 –  > Por Md Mahbubur Rahman.
  • Cum alegi după ce valoare de array să sortezi? de exemplu String[][] cat = new String[13][4]; Vreau să sortez după a 3-a coloană din fiecare rând. –  > Por Rick.
  • @Rick trebuie doar să modificați codul din public int Compare... pentru a specifica coloana după care doriți să sortați. [0] înseamnă prima coloană, deci pentru a patra coloană folosiți [3]. –  > Por Troyseph.
Costi Ciudatu
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;
    }
}

În acest fel puteți gestiona orice tip de date în aceste array-uri (atâta timp cât sunt comparabile) și puteți sorta orice coloană în ordine crescătoare sau descrescătoare.

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

PS: asigurați-vă că verificați dacă există ArrayIndexOutOfBounds și altele.

EDIT: Soluția de mai sus ar fi utilă doar dacă sunteți în măsură să stocați efectiv un java.util.Date în prima coloană sau dacă formatul de date vă permite să folosiți o simplă comparație de tip String pentru aceste valori. În caz contrar, trebuie să convertiți acel șir de caractere într-o dată, iar acest lucru se poate realiza folosind o interfață callback (ca soluție generală). Iată o versiune îmbunătățită:

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);
        }
    }
}

Și în acest moment, puteți sorta pe prima coloană cu:

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

Am sărit peste verificările pentru nulități și alte probleme de tratare a erorilor.

Sunt de acord că acest lucru începe să arate deja ca un cadru. 🙂

Ultima editare (sper): Abia acum îmi dau seama că formatul de date vă permite să folosiți o simplă comparație String. În acest caz, nu aveți nevoie de „versiunea îmbunătățită”.

Comentarii

  • +1, pentru soluția mai generală de a sorta după orice Obiect și pe orice coloană. –  > Por camickr.
  • Este o soluție generală bună, dar întrebarea, așa cum a fost pusă, solicită sortarea unui String[] unde fiecare String conține date în coloane. Titlul nu se potrivește cu întrebarea; acest răspuns satisface doar titlul… –  > Por dkarp.
Ron
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]);
    }
});

Vaibhav Agarwal
  1. instalați java8 jdk+jre

  2. folosiți expresie lamda pentru a sorta matrice 2D.

cod:

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

ieșire

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

João Silva

Presupunând că matricea dvs. conține șiruri de caractere, puteți utiliza următoarele:

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);
    }
});

Dacă aveți un array bidimensional, soluția este, de asemenea, foarte asemănătoare:

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);
    }
});

Comentarii

  • @dogbane Aruncați o privire la întrebare. Aceasta este nu de fapt un array 2D, chiar dacă titlul insistă că este. Este vorba de un array de Strings cu date în coloană în interior. De fapt, acest răspuns răspunde la întrebarea reală mai bine decât toate celelalte… –  > Por dkarp.
  • @dkarp de ce compari doar timpii? Ar trebui să comparați prima coloană, care este „aaaa.MM.dd HH:mm”. Uită-te din nou la întrebare. –  > Por dogbane.
  • @dogbane Oh, asta e o observație bună. (Totuși, nu este răspunsul meu.) Totuși, o bun răspuns la această întrebare ar trebui să o trateze ca pe o String[] cu date columnare în formatul descris de OP, nu ca un String[][]. Aș fi de-upvotat acest răspuns dacă aș fi văzut comentariul tău mai devreme, totuși… –  > Por dkarp.
  • @dogbane și @dkarp: Mulțumesc, mi-am editat răspunsul pentru a include data/ora în loc de doar ora. De asemenea, am adăugat o versiune pentru a sorta o matrice bidimensională, deși nu îmi este clar, având în vedere exemplul oferit de OP, că lucrează cu o matrice 2D. –  > Por João Silva.
  • @dkarp scuze, am crezut că este răspunsul tău. –  > Por dogbane.
camickr

Check out the ColumnComparator. Este practic aceeași soluție propusă de Costi, dar suportă și sortarea pe coloane într-o listă și are câteva proprietăți de sortare în plus.

ΦXocę 웃 Пepeúpa ツ

Utilizarea Lambdas începând cu 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));
    

Output:

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

luckyguy73

Dacă sunteți în căutarea unor one liners ușoare pentru a sorta matricea 2d, atunci iată-le.

Sortează String[][][] arr în ordine crescătoare după prima coloană

Arrays.sort(arr, (a, b) -> a[0].compareTo(b[0]);

Sortează String[][][] arr în ordine descrescătoare după prima coloană

Arrays.sort(arr, (a, b) -> b[0].compareTo(a[0]);

Sortează String[][][] arr în ordine crescătoare după a doua coloană

Arrays.sort(arr, (a, b) -> a[1].compareTo(b[1]);

Sortează String[][][] arr în ordine descrescătoare după a doua coloană

Arrays.sort(arr, (a, b) -> b[1].compareTo(a[1]);

Sort int[][][] arr în ordine crescătoare după prima coloană

Arrays.sort(arr, (a, b) -> Integer.compare(a[0], b[0]));

sau

Arrays.sort(arr, (a, b) -> a[0] - b[0]);

Sort int[][][] arr în ordine descrescătoare după prima coloană

Arrays.sort(arr, (a, b) -> Integer.compare(b[0], a[0]));

sau

Arrays.sort(arr, (a, b) -> b[0] - a[0]);

Sort int[][][] arr în ordine crescătoare după a doua coloană

Arrays.sort(arr, (a, b) -> Integer.compare(a[1], b[1]));

sau

Arrays.sort(arr, (a, b) -> a[1] - b[1]);

Sortează int[][] arr în ordine descrescătoare după a doua coloană

Arrays.sort(arr, (a, b) -> Integer.compare(b[1], a[1]));

sau

Arrays.sort(arr, (a, b) -> b[1] - a[1]);