Rename Duplicate Fields with a Separator
This example shows how to deal with records that contain two fields with the same name, which happens when a CSV header repeats a column or a join brings in a second copy of a field. RemoveDuplicateFields resolves the duplicates with a policy. The built-in DuplicateFieldsPolicy values keep all copies, keep only the first or the last, merge the values into an array, or rename the later copies with a numeric suffix; RENAME_UNDERSCORE puts an underscore before the number so Name becomes Name_1. A RenamePolicy lets you pick any separator. The separator matters when a field name itself ends in digits: with plain RENAME a duplicate of 2010 would become the ambiguous 20101, with a separator it becomes 2010_1.
Input CSV file
The header names the Name column twice.
Account,Name,LastName,Name 101,Keanu,Reeves,Keanu Reeves 102,John,Doe,John Doe 103,Jane,Doe,Jane Doe
Java Code Listing
package com.northconcepts.datapipeline.examples.cookbook;
import java.io.File;
import com.northconcepts.datapipeline.core.DataReader;
import com.northconcepts.datapipeline.core.StreamWriter;
import com.northconcepts.datapipeline.csv.CSVReader;
import com.northconcepts.datapipeline.job.Job;
import com.northconcepts.datapipeline.transform.RemoveDuplicateFields;
import com.northconcepts.datapipeline.transform.RemoveDuplicateFields.DuplicateFieldsPolicy;
import com.northconcepts.datapipeline.transform.RemoveDuplicateFields.RenamePolicy;
import com.northconcepts.datapipeline.transform.TransformingReader;
public class RenameDuplicateFieldsWithASeparator {
public static void main(String[] args) {
DataReader reader = new CSVReader(new File("example/data/input/duplicate_fields.csv"))
.setFieldNamesInFirstRow(true);
reader = new TransformingReader(reader)
.add(new RemoveDuplicateFields(DuplicateFieldsPolicy.RENAME_UNDERSCORE));
Job.run(reader, StreamWriter.newSystemOutWriter());
reader = new CSVReader(new File("example/data/input/duplicate_fields.csv"))
.setFieldNamesInFirstRow(true);
reader = new TransformingReader(reader)
.add(new RemoveDuplicateFields(new RenamePolicy("-")));
Job.run(reader, StreamWriter.newSystemOutWriter());
}
}
Code Walkthrough
- A
CSVReaderreadsduplicate_fields.csvwith field names in the first row, so every record has twoNamefields. - A
TransformingReaderappliesRemoveDuplicateFieldswithDuplicateFieldsPolicy.RENAME_UNDERSCORE; the secondNamefield is renamedName_1.Job.run()prints the records to aStreamWriter. - The file is read again, this time with
new RenamePolicy("-"), which renames each later duplicate to its name, the separator and the first unused number starting at 1:Name-1.
Console Output
-----------------------------------------------
0 - Record {
0:[Account]:STRING=[101]:String
1:[Name]:STRING=[Keanu]:String
2:[LastName]:STRING=[Reeves]:String
3:[Name_1]:STRING=[Keanu Reeves]:String
}
-----------------------------------------------
1 - Record {
0:[Account]:STRING=[102]:String
1:[Name]:STRING=[John]:String
2:[LastName]:STRING=[Doe]:String
3:[Name_1]:STRING=[John Doe]:String
}
-----------------------------------------------
2 - Record {
0:[Account]:STRING=[103]:String
1:[Name]:STRING=[Jane]:String
2:[LastName]:STRING=[Doe]:String
3:[Name_1]:STRING=[Jane Doe]:String
}
-----------------------------------------------
3 records
-----------------------------------------------
0 - Record {
0:[Account]:STRING=[101]:String
1:[Name]:STRING=[Keanu]:String
2:[LastName]:STRING=[Reeves]:String
3:[Name-1]:STRING=[Keanu Reeves]:String
}
-----------------------------------------------
1 - Record {
0:[Account]:STRING=[102]:String
1:[Name]:STRING=[John]:String
2:[LastName]:STRING=[Doe]:String
3:[Name-1]:STRING=[John Doe]:String
}
-----------------------------------------------
2 - Record {
0:[Account]:STRING=[103]:String
1:[Name]:STRING=[Jane]:String
2:[LastName]:STRING=[Doe]:String
3:[Name-1]:STRING=[Jane Doe]:String
}
-----------------------------------------------
3 records
