Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to nicely read "alternating" lines?

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?

like image 983
GhostCat Avatar asked Dec 27 '25 23:12

GhostCat


2 Answers

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) }
like image 123
Robby Cornelissen Avatar answered Dec 31 '25 00:12

Robby Cornelissen


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]) }