我正在开发一个使用Apache POI读取Excel文件的应用程序。我将单元格值放在String对象的矩阵内。
[title 1][title 2][title 3]
[mark] [smith] [34]
[simon] [black] [24]
我一直被要求允许根据所选列对矩阵进行排序。 如何订购String对象的矩阵?
谢谢
答案 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));
}
}
编辑:实现了一个自定义比较器,该比较器考虑了数字。