Java 如何计算.csv文件中的重复条目?

Java 如何计算.csv文件中的重复条目?,java,csv,parsing,Java,Csv,Parsing,我有一个.csv文件,格式如下: ID,date,itemName 456,1-4-2020,Lemon 345,1-3-2020,Bacon 345,1-4-2020,Sausage 123,1-1-2020,Apple 123,1-2-2020,Pineapple 234,1-2-2020,Beer 345,1-4-2020,Cheese 我已经实现了遍历文件、扫描第一个数字并按降序排序并生成新输出的算法: 123,1-1-2020,Apple 123,1-2-2020,Pineappl

我有一个.csv文件,格式如下:

ID,date,itemName
456,1-4-2020,Lemon
345,1-3-2020,Bacon
345,1-4-2020,Sausage
123,1-1-2020,Apple
123,1-2-2020,Pineapple
234,1-2-2020,Beer
345,1-4-2020,Cheese

我已经实现了遍历文件、扫描第一个数字并按降序排序并生成新输出的算法:

123,1-1-2020,Apple
123,1-2-2020,Pineapple
234,1-2-2020,Beer
345,1-3-2020,Bacon
345,1-4-2020,Cheese
345,1-4-2020,Sausage
456,1-4-2020,Lemon
我的问题是,我如何实现我的算法,使输出计数重复的第一个数字条目,并重新格式化,使其看起来像这样

123,1-1-2020,1,Apple
123,1-2-2020,1,Pineapple
234,1-2-2020,1,Beer
345,1-3-2020,1,Bacon
345,1-4-2020,2,Cheese,Sausage
456,1-4-2020,1,Lemon
…以便它计算每个ID的出现次数,用次数表示,如果该ID的日期也相同,则将项目名称合并到同一行。下面是我的源代码(.csv中的每一行都被制作成一个名为“receipt”的对象,该对象具有ID、日期和名称以及各自的get()方法):

公共类读取文件{
私有静态列表readFile(){
列表收据=新的ArrayList();
试一试{
BufferedReader=new BufferedReader(new FileReader(“dataset.csv”);
//移过第一个标题行
reader.readLine();
字符串行=reader.readLine();
//从第二行开始读取,直到EOF,在“,”处拆分每个字符串
while(行!=null){
String[]attributes=line.split(“,”);
收据属性=获取属性(属性);
receipts.add(属性);
line=reader.readLine();
}
reader.close();
}捕获(IOE异常){
e、 printStackTrace();
}
退货收据;
}
私有静态收据getAttributes(字符串[]属性){
//获取位于第一个“,”之前的ID
long memberNumber=long.parseLong(属性[0]);
//获取位于第一个“,”之后的日期
字符串日期=属性[1];
//获取位于第二个“,”后面的名称
字符串名称=属性[2];
返回新收据(会员编号、日期、姓名);
}
//排序后将数据解析为新文件
私有静态无效解析(列表收据){
PrintWriter输出=null;
试一试{
输出=新的PrintWriter(“output.txt”);
}catch(filenotfounde异常){
e、 printStackTrace();
}
//对于每个收据,断言文本输出流不为空,打印行。
收据(p:收据){
断言输出!=null;
println(p.getMemberNumber()+”,“+p.getDate()+”,“+p.getName());
}
断言输出!=null;
output.close();
}
//Main方法,接受输入文件,排序和解析
公共静态void main(字符串[]args){
列表收据=readFile();
快速排序q=新的快速排序();
q、 快速排序(收据);
分析(收据);
}
}

最简单的方法是使用地图

文件中的示例数据

String[] lines = {
"123,1-1-2020,Apple",
"123,1-2-2020,Pineapple",
"234,1-2-2020,Beer",
"345,1-3-2020,Bacon",
"345,1-4-2020,Cheese",
"345,1-4-2020,Sausage",
"456,1-4-2020,Lemon"};
  • 创建地图
  • 阅读这些行时,使用
    compute
    方法将它们拆分并添加到地图中。如果键(数字和日期)不存在,这会将行放入。否则,它只是将最后一项附加到现有条目
  • 文件不必排序,但遇到值时会将其添加到末尾

我不明白你的意思。在输出的两个单独的行上有345。我认为第一个数字是用来组合行的。永远不要将日期存储为MM-DD-YYYY或DD-MM-YYYY。始终是ISO 8601(YYYY-MM-DD)。@jarmod这可能是OP无法控制的要求。@Mint那么为什么要在第一行中结合苹果和菠萝呢。两个不同的日期,我确定了我的答案。
String[] lines = {
"123,1-1-2020,Apple",
"123,1-2-2020,Pineapple",
"234,1-2-2020,Beer",
"345,1-3-2020,Bacon",
"345,1-4-2020,Cheese",
"345,1-4-2020,Sausage",
"456,1-4-2020,Lemon"};
Map<String, String> map = new LinkedHashMap<>(); 
for (String line : lines) {
    String[] vals = line.split(",");

    // if v is null, add the line
    // if v exists, take the existing line and append the last value
    map.compute(vals[0]+vals[1], (k,v)->v == null ? line : v +","+vals[2]);
}

for (String line : map.values()) {
    String[] fields = line.split(",",3);
    int count = fields[2].split(",").length;
    System.out.printf("%s,%s,%s,%s%n", fields[0],fields[1],count,fields[2]);
}
123,1-1-2020,1,Apple
123,1-2-2020,1,Pineapple
234,1-2-2020,1,Beer
345,1-3-2020,1,Bacon
345,1-4-2020,2,Cheese,Sausage
456,1-4-2020,1,Lemon