Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to correctly get current loop count from a Iterator in scala

Tags:

scala

I am looping over the following lines from a csv file to parse them. I want to identify the first line since its the header. Whats the best way of doing this instead of making a var counter holder.

var counter = 0
for (line <- lines) {
  println(CsvParser.parse(line, counter))
  counter++
}

I know there is got to be a better way to do this, newbie to Scala.

like image 588
chiappone Avatar asked Jan 13 '12 18:01

chiappone


2 Answers

Try zipWithIndex:

for (line <- lines.zipWithIndex) {
  println(CsvParser.parse(line._1, line._2))
}

@tenshi suggested the following improvement with pattern matching:

for ((line, count) <- lines.zipWithIndex) {
  println(CsvParser.parse(line, count))
}
like image 122
Tomasz Nurkiewicz Avatar answered Nov 02 '22 03:11

Tomasz Nurkiewicz


I totally agree with the given answer, still that I've to point something important out and initially I planned to put in a simple comment.

But it would be quite long, so that, leave me set it as a variant answer.

It's prefectly true that zip* methods are helpful in order to create tables with lists, but they have the counterpart that they loop the lists in order to create it.

So that, a common recommendation is to sequence the actions required on the lists in a view, so that you combine all of them to be applied only producing a result will be required. Producing a result is considered when the returnable isn't an Iterable. So is foreach for instance.

Now, talking about the first answer, if you have lines to be the list of lines in a very big file (or even an enumeratee on it), zipWithIndex will go through all of 'em and produce a table (Iterable of tuples). Then the for-comprehension will go back again through the same amount of items.

Finally, you've impacted the running lenght by n, where n is the length of lines and added a memory footprint of m + n*16 (roughtly) where m is the lines' footprint.

Proposition

lines.view.zipWithIndex map Function.tupled(CsvParser.parse) foreach println

Some few words left (I promise), lines.view will create something like scala.collection.SeqView that will hold all further "mapping" function producing new Iterable, as are zipWithIndex and map.

Moreover, I think the expression is more elegant because it follows the reader and logical. "For lines, create a view that will zip each item with its index, the result as to be mapped on the result of the parser which must be printed".

HTH.

like image 7
Andy Petrella Avatar answered Nov 02 '22 04:11

Andy Petrella