0

When reading a CSV file, I want to remember/store data across multiple rows of that particular file, e.g. to make an object based on columns from line 1+2, line 3+4, etc.

While I've found a solution, I do believe there should a 'cleaner' solution for this. This is what I came up with:

public static void main(String[] args) {

    try (var reader = new FileReader("src/main/java/com/kdh/snippets/loops/dummy.csv")) {
        List<String[]> rows = CsvReader.read(reader);

        var index1 = 0;
        var index2 = 1;

        // 50 lines in file = 25 iterations
        for (int i = 0; i < rows.size() / 2; i++) {
            String[] consumption = rows.get(index1);
            String[] injection = rows.get(index2);
            System.out.println("Consumption: " + consumption[8] + ", Injection: " + injection[8]);
            index1 += 2;
            index2 += 2;
        }
    } catch (IOException ex) {
        System.out.println(ex);
    }
}
kdh
  • 1
  • 1
  • 1
    tbh: This looks totally fine. There may be a performance problem when you get a `List` that has no `O(1)` access time on its `get()` method (i.e. when using a `LinkedList`). An alternative would be to use an `iterator()` on which you just call `next()` twice per iteration – Lino Oct 25 '22 at 13:44

1 Answers1

0

I do believe there should a 'cleaner' solution for this.

It's not clear what you have in mind when you say "cleaner", but here are some suggestions that I think would improve your code:

  1. Consider reading CSV lines as you need them, instead of slurping them all into memory first, then going back and iterating over them. If you were using the CsvReader of OpenCSV, then that would imply using the readNext() method instead of the readAll() method. It's unclear if or how the same could be done with the unspecified CsvReader you're actually using.

  2. Use an object that represents the current state of the iteration instead of iterating by index. If you persist in collecting all the lines into a List, then that would mean using the list's Iterator to obtain individual lines. If you implement the above suggestion (1), then the CsvReader itself would be the wanted object.

  3. With (2) in place, simply loop until the source of lines has no more (pairs of) lines to provide.

For example,

public static void main(String[] args) {

    try (var reader = new CsvReader(
            new FileReader("src/main/java/com/kdh/snippets/loops/dummy.csv"))) {
        for (String[] line = reader.nextLine(); line != null; line = reader.nextLine()) {
            String consumption = line[8];

            line = reader.nextLine();
            if (line == null) {
                // warn about an odd number of lines?
                break;
            }
            String injection = line[8];

            System.out.println("Consumption: " + consumption + ", Injection: " + injection);
        }
    } catch (IOException ex) {
        System.out.println(ex);
    }
}
John Bollinger
  • 160,171
  • 8
  • 81
  • 157