基于一列对二维数组进行排序

Posted

技术标签:

【中文标题】基于一列对二维数组进行排序【英文标题】:Sort a two dimensional array based on one column 【发布时间】:2011-06-21 21:59:51 【问题描述】:

在 Java 中,我的数组中有如下数据

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

我想根据第一列对它进行排序,所以我的最终数据可以是这样的

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

第一列是格式“yyyy.MM.dd HH:mm”的日期,第二列是字符串。

【问题讨论】:

【参考方案1】:

如果您正在寻找一种简单的方法来对二维数组进行排序,那么就可以了。

按第一列升序排序字符串[][] arr

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

按第一列降序排列字符串[][] arr

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

按第二列升序排序字符串[][] arr

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

按第二列降序排列字符串[][] arr

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

int[][] arr 按第一列升序排序

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

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

int[][] arr 按第一列降序排序

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

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

int[][] arr 按第二列升序排序

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

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

int[][] arr 按第二列降序排序

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

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

【讨论】:

【参考方案2】:

从 java 8 开始使用 Lambda:

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

输出:

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

【讨论】:

【参考方案3】:

    安装java8 jdk+jre

    使用lamda表达式二维数组进行排序。

代码:

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

输出

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

【讨论】:

【参考方案4】:
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;
    

通过这种方式,您可以处理这些数组中的任何类型的数据(只要它们是可比较的),并且您可以按升序或降序对任何列进行排序。

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

PS:请务必检查ArrayIndexOutOfBounds 和其他人。

编辑:只有当您能够在第一列中实际存储java.util.Date 或您的日期格式允许您对这些值使用纯字符串比较时,上述解决方案才会有帮助。否则,您需要将该字符串转换为日期,您可以使用回调接口(作为通用解决方案)来实现。这是一个增强版:

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

此时,您可以使用以下命令对第一列进行排序:

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

我跳过了对空值和其他错误处理问题的检查。

我同意这已经开始看起来像一个框架了。 :)

最后(希望)编辑:我现在才意识到您的日期格式允许您使用纯字符串比较。如果是这样,你就不需要“增强版”了。

【讨论】:

+1,用于按任何对象和任何列排序的更通用的解决方案。 这是一个很好的通用解决方案,但提出的问题要求对String[] 进行排序,其中每个String 都包含列数据。标题与问题不符;这个答案只满足标题...【参考方案5】:

根据一列对二维数组进行排序 第一列为“yyyy.MM.dd HH:mm”格式的日期,第二列为字符串。

既然你说二维数组,我假设“格式的日期......”是指一个字符串。下面是对 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]);
        
    


输出:

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

【讨论】:

简单!我试过了,它按预期工作 - 谢谢 - 标记为正确答案 @emaillenin - 很高兴能提供帮助 @BertF,很有帮助。如果我想按自然顺序进行比较,我应该怎么做? +1 表示不错的答案。 :) 如何选择要排序的数组值?例如 String[][] cat = new String[13][4];我想按每行的第 3 列排序。 @Rick 您只需更改public int Compare... 方法中的代码即可指定要排序的列。 [0] 表示第一列,因此第四列使用[3]【参考方案6】:

查看ColumnComparator。它与 Costi 提出的解决方案基本相同,但它也支持对 List 中的列进行排序,并具有更多的排序属性。

【讨论】:

【参考方案7】:

假设您的数组包含字符串,您可以使用以下内容:

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

如果有二维数组,解法也很相似:

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

【讨论】:

@dogbane 看看这个问题。它不是实际上是一个二维数组,尽管标题坚持它是。这是一个Strings 数组,里面有列数据。事实上,这个回答比其他所有回答都更好地解决了实际问题...... @dkarp 你为什么只比较时间?您应该比较第一列“yyyy.MM.dd HH:mm”。再看看这个问题。 @dogbane 哦,这很好。 (但是,不是我的答案。)不过,对这个问题的 答案应该将其视为具有 OP 描述的格式的柱状数据的 String[],而不是 String[][]。如果我早些时候看到你的评论,我会反对这个,不过...... @dogbane 和@dkarp:谢谢,我已经编辑了我的答案以包含日期/时间,而不仅仅是时间。我还添加了一个版本来对二维数组进行排序,但我并不清楚给出的示例,OP 提供了他正在使用二维数组。 @dkarp 抱歉,我以为这是你的答案。【参考方案8】:
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]);
    
);

【讨论】:

以上是关于基于一列对二维数组进行排序的主要内容,如果未能解决你的问题,请参考以下文章

如何按列对二维数组(锯齿状)进行排序[重复]

基于列对二维向量数组进行排序

在C#中按列对二维数组进行排序

JAVA中如何对二维数组的每一列进行排序

如何在 C# 中对二维(矩形)数组进行排序?

JAVA中如何对二维数组的每一列进行排序