比较CSV中的两个arrayLists



我有一个一般性问题:

根据彼此的值对两个数组进行排序的最佳方法是什么?如果:

(1( 每个arrayList只包含一列导入的CSV(通过inputStream和bufferReader((为了方便起见,我不会在下面打印(。

//my arrayLists:
List <String> OpenVal = new Arraylist ();
List <String> CloseVal = new Arraylist();

//lists from above contain column 0 and 1 from CSV:
while((reader.readLine()) != null) {
Sting line = "";
String ColTwo [] = line.split(",");
openVal.add(colOne[1]);
closVal.add(colOne[2]);

(2( 为了更清楚,CSV[colOne[1],colOne[2]的每一列都包含以下信息:

//colOne [1]  colOne [2]
date        value
friday       32
tues         21
wed          5

(3( 我对它的排序方式是这样的(按值(:

//colOne [1]  colOne [2]
date        value
wed          5
tues         21
friday       32

(4( 我不认为比较器类是有效的,因为我不需要向arraylist的构造函数写入信息。该列表以CSV为前缀。

(3( 比较这两个列表的最佳方式是什么?

如果您的csv每个日期只包含一行,您可以将数据存储到映射而不是列表:

Map<String,Integer> myMap = new HashMap<>();
String line;
while((line = reader.readLine()) != null) {
myMap.put(line.split(",")[0], Integer.parseInt(line.split(",")[1]));
}

之后,您可以对地图进行排序:

Map<String,Integer> sorted = myMap.entrySet().stream().
sorted(Map.Entry.comparingByValue()).
collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,(e1, e2) -> e1,LinkedHashMap::new));

并打印您的排序地图:

sorted.entrySet().forEach(System.out::println);

或者正如DodgyCodeException所评论的,将您的行读取到List<String[]>:

List<String[]> myList = new ArrayList<>();
String line = "";
while((line = reader.readLine()) != null) {
myList.add(line.split(","));
}

和排序:

Collections.sort(myList, new Comparator<String[]>() {
@Override
public int compare(String[] o1, String[] o2) {
return Integer.compare(Integer.parseInt(o1[1]), Integer.parseInt(o2[1]));
}
});

最后,要打印您的列表,只需使用for循环,例如:

for(String[] row : myList){
System.out.println(row[0] +" : "+ row[1])
}

我能想到两种比解析成单独的面向列的数组更好的方法。

  • 编写一个包含成员字段的类来保存您的值,并用其单个方法compareTo实现Comparable接口。将对象实例化并收集到List中,然后调用Collections.sort。如果您有进一步的工作要做,或者您有额外的业务逻辑要放在某个地方,那么这种方法是最好的
  • 使用库解析CSV文件,并编写一些代码对生成的元组进行排序

我将展示第二个。

Apache Commons CSV库

Apache Commons CSV库在读写逗号分隔值或制表符分隔文件方面对我来说效果很好。令人惊讶的是,这些格式有多种变体Commons CSV至少处理其中的九个。

首先,创建一个示例数据文件。我冒昧地将day-of-week的第一个专栏标题从date更改为dow,以更准确地说。

dow,value
friday,32
wed,5
tues,21

Commons CSV库返回CSVRecord对象的Iterable。CSV包含已解析CSV数据行中每列的值。所以我们可以将这些对象用作元组。

List.sort静态方法将为我们收集的元组(CSVRecord对象(进行排序。我们需要提供一个Comparator方法来对每个元组进行比较。对于每个元组,我们根据数据文件第一行中定义的名称提取第二列,即数据文件中的名称value

List < CSVRecord > tuples = new ArrayList <>( 3 );
Reader reader = null;
try {
reader = new FileReader( "/Users/basilbourque/data.csv" );
CSVFormat csvFormat = CSVFormat.RFC4180.withIgnoreSurroundingSpaces( true ).withHeader();
Iterable < CSVRecord > iterable = csvFormat.parse( reader );
// Convert `Iterable` to a `List`. 
for ( CSVRecord record : iterable ) {
tuples.add( record );
}
} catch ( FileNotFoundException e ) {
e.printStackTrace();
} catch ( IOException e ) {
e.printStackTrace();
}
Comparator < CSVRecord > comparator = new Comparator < CSVRecord >() {
@Override
public int compare ( CSVRecord o1 , CSVRecord o2 ) {
Integer a = Integer.valueOf( o1.get( "value" ) );
Integer b = Integer.valueOf( o2.get( "value" ) );
return a.compareTo( b );
}
};
System.out.println( "tuples before sort: n" + tuples );
tuples.sort( comparator );
System.out.println( "tuples after sort: n" + tuples );

排序前的元组:

[CSRecord[注释=null,映射={dow=0,value=1},recordNumber=1,values=[星期五,32]],CSVRecord[评论=null,映像={dow=0,value=1},记录编号=2,values=[wed,5]],CSVRecord[注意=null,贴图={dow=0,value=1}、记录编号=3,values=[tues,21]]]

排序后的元组:

[CSRecord[注释=null,映射={dow=0,value=1},recordNumber=2,values=[wed,5]],CSVRecord[评论=null,贴图={dow=0,value=1},recordNumber=3,values=[tues,21]],CSVRecord[注释=null,映射={dow=0,value=1},记录编号=1,values=[friday,32]]]

最后,循环现在排序的元组列表,使用CSVRecord::get提取数据以用于其他目的。

最新更新