| Author |
Nested for loops to the point of confusion
|
Dustin Schreader
Ranch Hand
Joined: May 25, 2009
Posts: 74
|
|
I get pretty confused when I have too many nested for loops. I've just about got this thing to work, it's reading in from a CSV file and I've got it to save one line of the CSV file to one portion of the array but it's only the last line from the CSV file. Any idea how to get the array to contain every row of the CSV file or maybe a more simple way to accomplish this?
|
 |
Winston Gutkowski
Bartender
Joined: Mar 17, 2011
Posts: 4726
|
|
Dustin Schreader wrote:Any idea how to get the array to contain every row of the CSV file or maybe a more simple way to accomplish this?
Well Lists are always useful, because you don't need to know how big they're going to be when you start.
A List<String> would be fine for keeping lines, but since you need to split the lines up too, you need to have a list of lists, viz:
List<List<String>>
and the most common class for using with arrays is ArrayList; so you end up with:
List<List<String>> csvFile = new ArrayList<List<String>>();
Another very useful method to know about is Arrays.asList(), which takes an array and returns it as a List.
So, putting it all together, your process loop might look something like:Once you have this, csvFile.get() will return you a row (as a List), so:
List<String> firstRow = csvFile.get(0);
and then you can use get() again to return an element, viz:
String thirdElement = firstRow.get(2);
You can also use for-each loops, just like you would with an array:
HIH
Winston
|
Isn't it funny how there's always time and money enough to do it WRONG?
|
 |
Winston Gutkowski
Bartender
Joined: Mar 17, 2011
Posts: 4726
|
|
Just in case you found the code I posted hard to follow, this line:
csvFile.add( Arrays.asList( dataRow.split(",") ) );
might be worthy of a bit of extra explanation, because it does quite a lot of stuff.
First remember that csvFile is a 'List of List of Strings'. It sounds quite a mouthful but in fact it's fairly straightforward:
1. The Strings are your String elements.
2. Each row in the file is a List of Strings (very similar to a String[]).
3. The file is a List of rows, ie, a List of List of Strings.
Going back to the line above and breaking it down:
You originally had a field called 'dataArray', OK:
String[] dataArray = dataRow.split(",");
now, as I explained before , Arrays.asList() will turn that into a List, so:
List<String> row = Arrays.asList(dataArray);
and finally, we have to add that "row" to the file:
csvFile.add(row);
All that first line does is do it all in one go, without having to create all those interim fields.
Sorry if it was unclear.
Winston
|
 |
Dustin Schreader
Ranch Hand
Joined: May 25, 2009
Posts: 102
|
|
|
My goal is to read in from CSV file and then add a new item to it and then write all the info back to the CSV file. That way it looks like I just added something new to the CSV file. I suppose I should have mentioned that before, would there be an easier way of doing this?
|
 |
Dustin Schreader
Ranch Hand
Joined: May 25, 2009
Posts: 102
|
|
I get an error for
It can't find the symbol method append(java.util.List<java.util.list<java.lang.String>>)
|
 |
Dustin Schreader
Ranch Hand
Joined: May 25, 2009
Posts: 102
|
|
I managed to simplify my original code a lot but I'm getting an error for incompatible types and I'm not sure how to get around it.
|
 |
Dustin Schreader
Ranch Hand
Joined: May 25, 2009
Posts: 102
|
|
I got it!
|
 |
Winston Gutkowski
Bartender
Joined: Mar 17, 2011
Posts: 4726
|
|
Dustin Schreader wrote:I got it!
Well done, but I'm afraid it's redundant.
If you look at the documentation for BufferedReader.readline(), you'll see that it already returns "the contents of the line, not including any line-termination characters".
Therefore:
dataArray = dataRow.split("\n");
will return exactly 1 element, so
rows[x] = dataArray[0];
is exactly the same thing as
rows[x] = dataRow;
Since, in your original code, you were splitting the line, I assumed that you needed to store all the CSV elements separately. Apologies for any confusion.
Winston
|
 |
Winston Gutkowski
Bartender
Joined: Mar 17, 2011
Posts: 4726
|
|
Dustin Schreader wrote:My goal is to read in from CSV file and then add a new item to it and then write all the info back to the CSV file. That way it looks like I just added something new to the CSV file. I suppose I should have mentioned that before, would there be an easier way of doing this?
Well if you need to add a new element to a line (unless it's only at the beginning or end) you're likely to have to split each line into elements, and that means either making it a String[] or a List<String>, as I suggested. The advantage of a List is that you don't have to worry about resizing; the class (eg, ArrayList) does it for you.
If you may also need to insert an entire row, then you're probably going to need some way of storing the file contents as a matrix.
Again, you have two choices:
String[][] (a two-dimensional String array) or a List<List<String>> (as I described above); and again, the advantage of using a List is that you don't need to worry about the resizing - although I admit, it does look a bit more verbose.
Winston
|
 |
Joanne Neal
Rancher
Joined: Aug 05, 2005
Posts: 3011
|
|
Winston Gutkowski wrote:Well if you need to add a new element to a line (unless it's only at the beginning or end) you're likely to have to split each line into elements, and that means either making it a String[] or a List<String>, as I suggested. The advantage of a List is that you don't have to worry about resizing; the class (eg, ArrayList) does it for you.
If you may also need to insert an entire row, then you're probably going to need some way of storing the file contents as a matrix.
Again, you have two choices:
String[][] (a two-dimensional String array) or a List<List<String>> (as I described above); and again, the advantage of using a List is that you don't need to worry about the resizing - although I admit, it does look a bit more verbose.
Winston
Actually you should create a Student class with a constructor that accepts the CSV line as a parameter. The constructor should then separate out the CSV elements and store them in instance variables. It would then need setter methods to modify the values. It can also override the toString method to output the values in a CSV format.
Note also that your method of splitting up the CSV line won't work if any of the elements contain commas. You are better off using a third party CSV library that will handle things like this.
|
Joanne
|
 |
Winston Gutkowski
Bartender
Joined: Mar 17, 2011
Posts: 4726
|
|
Joanne Neal wrote:Actually you should create a Student class with a constructor that accepts the CSV line as a parameter...
Absolutely. My answer was geared more to OP's original code.
Winston
|
 |
Wendy Gibbons
Bartender
Joined: Oct 21, 2008
Posts: 1098
|
|
Joanne Neal wrote:
Note also that your method of splitting up the CSV line won't work if any of the elements contain commas. You are better off using a third party CSV library that will handle things like this.
people wouldn't allow commas in a csv file would they... *falls off chair laughing at her own joke*
|
 |
Dustin Schreader
Ranch Hand
Joined: May 25, 2009
Posts: 102
|
|
Winston Gutkowski wrote:
Well done, but I'm afraid it's redundant.
If you look at the documentation for BufferedReader.readline(), you'll see that it already returns "the contents of the line, not including any line-termination characters".
Therefore:
dataArray = dataRow.split("\n");
will return exactly 1 element, so
rows[x] = dataArray[0];
is exactly the same thing as
rows[x] = dataRow;
Since, in your original code, you were splitting the line, I assumed that you needed to store all the CSV elements separately. Apologies for any confusion.
Winston
I tried
but I got an error
1 error found:
File: /Users/doodthatscool/Desktop/StudentsClass.java [line: 24]
Error: /Users/doodthatscool/Desktop/StudentsClass.java:24: incompatible types
found : java.lang.String[]
required: java.lang.String
|
 |
Campbell Ritchie
Sheriff
Joined: Oct 13, 2005
Posts: 32599
|
|
|
That is because rows is an array of Strings, not an array of String arrays.
|
 |
 |
|
|
subject: Nested for loops to the point of confusion
|
|
|