如何订购对象矩阵

时间:2019-05-28 08:33:33

标签: java

我正在开发一个使用Apache POI读取Excel文件的应用程序。我将单元格值放在String对象的矩阵内。

[title 1][title 2][title 3]
[mark]   [smith]  [34]
[simon]  [black]  [24]

我一直被要求允许根据所选列对矩阵进行排序。 如何订购String对象的矩阵?

谢谢

2 个答案:

答案 0 :(得分:2)

如果只有几列,则可以使用有意义的名称创建一些比较器,并按如下所示进行排序:

    public static void main(String[] args) {
    String[][] matrix = {{"mark","smith","34"},
                         {"simon","black","24"},
                         {"foo","bar","44"}
                        };        

    Comparator<String[]> firstNameComparator  = new Comparator<String[]>() {
        @Override
        public int compare(String[] row1, String[] row2) {
            return row1[0].compareTo(row2[0]);
        }
    };
    Comparator<String[]> lastNameComparator  = new Comparator<String[]>() {
        @Override
        public int compare(String[] row1, String[] row2) {
            return row1[1].compareTo(row2[1]);
        }
    };
    Comparator<String[]> ageComparator  = new Comparator<String[]>() {
        @Override
        public int compare(String[] row1, String[] row2) {
            return Integer.compare(Integer.parseInt(row1[2]), Integer.parseInt(row2[2]));
        }
    };
    Arrays.sort(matrix, firstNameComparator);// pass the desired comparator
    for(String[] row:matrix){
        System.out.println(Arrays.toString(row));
    }
}

或创建一个扩展Comparator并传递列索引的类:

public class NewClass5 {
    public static void main(String[] args) {
        String[][] matrix = {{"mark","smith","34"},
                             {"simon","black","24"},
                             {"foo","bar","44"}
                            }; 

        Arrays.sort(matrix, new CompareByColumn(1));// pass the desired index
        for(String[] row:matrix){
            System.out.println(Arrays.toString(row));
        }
    }
    static class CompareByColumn implements Comparator {
        int columnToSort;
        CompareByColumn(int columnToSort) {
            this.columnToSort = columnToSort;
        }
        public int compare(Object o1, Object o2) {
                String[] row1 = (String[]) o1;
                String[] row2 = (String[]) o2;
                return row1[columnToSort].compareTo(row2[columnToSort]);
        }
    }    
}

使用Java 8和流,您可以更紧凑地编写它:

String[][] sorted = Arrays.stream(matrix)
                          .sorted((s1,s2)->s1[1].compareTo(s2[1])) // pass the desired index
                          .toArray(String[][]::new);
for(String[] row: sorted){
    System.out.println(Arrays.toString(row));
}

编辑

由于您更喜欢流方法,因此我仅对此进行了重新设计。但是您也可以将其用于其他方法。您可以在比较之前检查相应的列是否包含数字,并以简单的if-else进行比较,以比较数字或字符串。

    int colIndex  = 2;
    String[][] sorted = Arrays.stream(matrix).sorted((s1,s2)-> {
                            if(s1[colIndex].matches("(\\d+(?:\\.\\d+)?)")){
                                return Double.compare(Double.parseDouble(s1[colIndex]), Double.parseDouble(s2[colIndex]));
                            }
                            else{
                                return s1[2].compareTo(s2[2]);
                            }}) 
                      .toArray(String[][]::new);

    for(String[] row: sorted){
        System.out.println(Arrays.toString(row));
    }

使用此(\d+(?:\.\d+)?)正则表达式来匹配整数和浮点数。

答案 1 :(得分:1)

首先,感谢您提出这个问题,事实证明,可视化和实施此解决方案是一项精神上的挑战。我希望以下解决方案是您想要的。

我写了一种方法,可以为您排序矩阵。该方法采用String矩阵作为参数,并返回一个新的String矩阵,其中每一列均按字母顺序排序。排序与其他列无关,因此无需外部上下文即可对每个列进行排序。

不幸的是,它没有将标题排除在排序过程之外,因此,如果您需要这样做,请告诉我,我会尽力实现。

public static boolean isNumeric(String str) {
    return str.matches("^[0-9]+$");
}

public static String[][] sortMatrix(String[][] matrix)
{
    int matrixLength = matrix[0].length;

    String[][] sortedMatrix = new String[matrixLength][];
    java.util.List<String[]> columns = new java.util.ArrayList<>();

    for (int i1 = 0; i1 < matrixLength; i1++)
    {
        String[] column = new String[matrixLength];
        for (int i2 = 0; i2 < matrixLength; i2++) {
            column[i2] = matrix[i2][i1];
        }
        columns.add(column);
    }

    // First sort the column before proceeding
    columns.forEach(column -> Arrays.sort(column, new Comparator<String>()
    {
        public int compare(String s1, String s2)
        {
            boolean i1 = isNumeric(s1);
            boolean i2 = isNumeric(s2);

            if (i1 && i2) {
                return Integer.valueOf(s1).compareTo(Integer.valueOf(s2));
            }
            else if (!i1) {
                return 1;
            }
            else return -1;
        }
    }));

    for (int i1 = 0; i1 < columns.size(); i1++)
    {
        String[] row = new String[matrixLength];
        for (int i2 = 0; i2 < matrixLength; i2++) {
            row[i2] = columns.get(i2)[i1];
        }
        sortedMatrix[i1] = row;
    }
    return sortedMatrix;
}

public static void main(String[] args) throws IOException {

    String[][] matrix = new String[3][] ;
    matrix[0] = new String[] { "title 1", "title 2", "title 3" };
    matrix[1] = new String[] { "simon", "1", "10" };
    matrix[2] = new String[] { "mark", "35", "2" };

    matrix = sortMatrix(matrix);
    for (String[] row : matrix) {
        System.out.println(Arrays.toString(row));
    }
}

编辑:实现了一个自定义比较器,该比较器考虑了数字。