I have a number of large files where I want to process all but the last line in each file. If the files were small, I could just convert to a TraversableLike and use the "init" method, e.g.:
lines.toList.init
But the files are large so I need to keep things as an iterator. Is there a simple way to get something like "init" on an Iterator? I'm considering the following, but I'm not confident it will always work:
lines.takeWhile(_ => lines.hasNext)
To get the last element in an iterator loop you can use std::next() (from C++11). The loop is generally terminated by iterator != container. end() , where end() returns an iterator that points to the past-the-end element.
An iterator is not a collection, but rather a way to access the elements of a collection one by one. The two basic operations on an iterator it are next and hasNext. A call to it. next() will return the next element of the iterator and advance the state of the iterator.
Unlike operations directly on a concrete collection like List , operations on Iterator are lazy. A lazy operation does not immediately compute all of its results.
You're relying on takeWhile
grabbing the next line first, and then checking to see if there is another line. It does work this way in the default iterator. And for any particular iterator, I expect that if it ever works, it should always work.
If it ever fails, you'll need to cache the result. You could make your own iterator that does this, or, more easily (if this isn't urgently performance-critical code):
lines.sliding(2).map(_.head)
Test this out as follows:
List(1,2,3,4,5).iterator.sliding(2).map(_.head).toList
You do not have to rely upon takeWhile
or any other method behaving any particular way; if sliding
is not broken, it will have the behavior above.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With