java - 在java中按列标题对二维列表进行排序
问题描述
我正在做一个可以读取和写入 CSV 的简单数据框,并包含按列排序的排序功能。如何通过输入列标题对正确的列进行排序,并从排序中排除列标题行?
这是 CSV 文件的示例数据:
Name,Age,Salary
Lim,20,2000
Tan,20,3000
Mah,19,2500
Roger,10,4000
我已经声明了我的 2D 列表,数据将如下所示:
List<List<String>> COLUMNDATA = new ArrayList();
COLUMNDATA = [[Name, Age, Salary], [Lim, 20, 2000], [Tan, 20, 3000], [Mah, 19, 2500], [Roger, 10, 4000]]
我想通过传入列标题对正确的列进行排序,并且列标题行不包含在排序中。例如:
COLUMNDATA.sort(“Age”)
所以它会变成这样:
Name,Age,Salary
Roger,10,4000
Mah,19,2500
Lim,20,2000
Tan,20,3000
我用过Comparator
and Collections.sort
,现在卡住了。如何实现我想要的功能?
final Comparator<List<String>> comparator = new Comparator<List<String>>() {
@Override
public int compare(List<String> object1, List<String> object2) {
return object1.get(1).compareTo(object2.get(1));
}
};
Collections.sort(COLUMNDATA, comparator);
for (List<String> list : COLUMNDATA) {
System.out.println(list);
}
解决方案
这是按照您的要求进行操作的方法。一旦定义了比较器,只需sublist
从列表 1 开始排序,跳过标题。由于它是原始列表的视图,它仍然对所需项目进行排序。
首先在要排序的字段上制作字段映射。如果你愿意,你可以不区分大小写。对于此示例,大小写很重要。
static Map<String, Integer> sortingFields = new HashMap<>();
static {
List<String> columns = List.of("Name", "Age", "Salary");
for (int i = 0; i < columns.size(); i++) {
sortingFields.put(columns.get(i), i);
}
}
创建列表列表。
List<List<String>> data = new ArrayList<>();
data.add(new ArrayList<>(List.of("Name" ,"Age", "Salary")));
data.add(new ArrayList<>(List.of("Lim", "20", "4000")));
data.add(new ArrayList<>(List.of("Tan", "20", "3000")));
data.add(new ArrayList<>(List.of("Mah", "19", "2500")));
data.add(new ArrayList<>(List.of("Roger", "10", "3500")));
现在调用排序和打印
sort("Age", data);
data.forEach(System.out::println);
印刷
[Name, Age, Salary]
[Roger, 10, 3500]
[Mah, 19, 2500]
[Lim, 20, 4000]
[Tan, 20, 3000]
这是排序方法。
public static void sort(String Column, List<List<String>> data) {
// use the column string to select the column number to sort.
Comparator<List<String>> comp =
(a, b) -> a.get(sortingFields.get(column))
.compareTo(b.get(sortingFields.get(column)));
data.subList(1,data.size()).sort(comp);
}
这就是我建议您组织数据并进行排序的方式。
首先创建一个类,如图所示。然后使用数据用类的实例填充列表。然后只需指定要排序的 getter。您可以根据需要添加任意数量的附加字段及其 getter。
原因是它允许混合类型存储在同一个对象中并且仍然可以排序。如果您对 a 进行排序String number
,它将排序lexcally
而不是numerically
. 除非您转换为整数,否则这将是一个问题(要查看此内容,请更改4000
为400
上面的薪水并对其进行排序)。但是,如果要对名称进行排序,则需要一个不同的比较器,因为将非 int 转换为 int 会引发异常。这一切都可以在一定程度上得到缓解,但它不像创建一个类那么简单。
通过简单地将方法引用更改为所需getter
的,您可以List
对任何字段进行排序。如果不存在 getter,并且该字段是公共的(不推荐),您可以使用 lambda。
public class SortingByColumn {
public static void main(String[] args) {
List<Person> data = new ArrayList<>();
data.add(new Person("Lim", 20, 2000));
data.add(new Person("Tan", 20, 3000));
data.add(new Person("Mah", 19, 2500));
data.add(new Person("Roger", 10, 4000));
List<Person> sorted = data.stream()
.sorted(Comparator.comparing(Person::getAge))
.collect(Collectors.toList());
System.out.printf("%10s %10s %10s%n", "Name","Age","Salary");
sorted.forEach(System.out::println);
}
static class Person {
private String name;
private int age;
private int salary;
public Person(String name, int age, int salary) {
this.name = name;
this.age = age;
this.salary = salary;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public int getSalary() {
return salary;
}
@Override
public String toString() {
return String.format("%10s %10s %10s", name, age,
salary);
}
}
}
印刷
Name Age Salary
Roger 10 4000
Mah 19 2500
Lim 20 2000
Tan 20 3000
推荐阅读
- javascript - Javascript Pretty Print Format 给出错误的结果
- javascript - React Modal 提前关闭
- r - 是否有将分类变量转换为连续变量的 R 函数?
- python - Python for loop zip 函数的输出字典比旧字典的输入键多
- node.js - Socket io 广播方法也从第二个动作向发送者广播
- python - Beaglebone Black 和 MCP230xx CircuitPython 库
- algorithm - 多边形中的点 3d(同一平面)算法
- javascript - 如何在 AngularJS 1.x 中使用 Jasmine 和 Karma 获取单选按钮的 ng-model 值
- powershell - 如何结合 Get-ChildItem 和 Get-FileHash 输出?电源外壳
- python - NumPy 中的链式比较?