I have a text file that contains lines that follow an alternate pattern, like:
name: SomeName
counterA: 0, counterB: 0, counterC: 0
name: SomeNameB
counterA: 1, counterB: 2, counterC: 3
...
I want to write a simple parser that pushes SameName, and the counters A to C into a new object.
So the task is basically to process always two lines together.
I started with this code:
fun readFileAsLinesUsingReadLines(fileName: String): List<String> = File(fileName).readLines()
fun main(args: Array<String>) {
val lines = readFileAsLinesUsingReadLines("Whatever")
for (i in (0 .. lines.size-1 step 2)) {
println(lines[i]+lines[i+1])
}
}
and yes, that prints
name: SomeName counterA: 0, counterB: 0, counterC: 0
which I can then further parse.
But I find that usage of (0 .. lines-size-1 step) to be not very elegant.
Are there more elegant, or "more kotlin" ways of pulling that information?
With useLines, you can read the lines as a (lazy) sequence, and then use chunked with a transform lambda to parse and format as you see fit:
val result = File("file.txt").useLines { lines ->
lines.chunked(2) { (l1, l2) -> l1 + l2 }.toList()
}
result.forEach { println(it) }
If, for some reason, you want to stream everything into memory first, you can also use readLines with the list-based version of chunked:
val result = File("file.txt").readLines().chunked(2) { (l1, l2) -> l1 + l2 }
result.forEach { println(it) }
Another way:
(0 until lines.size).filter { it % 2 == 0 }.forEach { println(lines[it] + lines[it+1]) }
or as Roland prefers:
lines.indices.filter { it % 2 == 0 }.forEach { println(lines[it] + lines[it+1]) }
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