Home > Back-end >  Group lines of text to a map using Kotlin.Collections functions
Group lines of text to a map using Kotlin.Collections functions

Time:10-09

Let's say I have a text file with contents like this:

[John]
likes: cats, dogs
dislikes: bananas
other info: is a man baby

[Amy]
likes: theater
dislikes: cosplay

[Ghost]

[Gary]
age: 42

Now, this file is read to a String. Is there a way to produce a Map<String, List<String>> that would have the following content:

Key: "John"
Value: ["likes: cats, dogs", "dislikes: bananas"., "other info: is a man baby"]

Key: "Amy"
Value: ["likes: theater", "dislikes: cosplay"]

Key: "Ghost"
Value: []

Key: "Gary"
Value: ["age: 42"]

that is to say, is there a sequence of Kotlin.Collections operators that would take the key from the brackets and take all the following lines as a value for that key, collecting all these key-value pairs into a map? The number of lines belonging to any given entry is unknown beforehand - there might be any amount of lines of properties, including zero lines.

I'm aware this is trivial to implement without Kotlin.Collections; the question is, is there a (possibly elegant) way of doing it with the Collections operations?

CodePudding user response:

You can do it like this:

text.split("\n\n")
    .associate {
        val lines = it.split("\n")
        lines[0].drop(1).dropLast(1) to lines.drop(1)
    }

Try it yourself

Here, we first divide the entire text into a list (by splitting with consecutive new lines) where each element contains data for one person. Next we use associate to convert the list into a map by mapping each list element to a map entry. To get the map entry we first get the lines from person data string. The key is lines[0].drop(1).dropLast(1) i.e. first line after removing the first ([) and last (]) characters. The value is the list of all lines except the first one.

CodePudding user response:

This might work, this divides the content by [ and then take the remaining elements for each group.

text.split("\\s(?=\\[)".toRegex())
    .map { it.split("\n").filter(String::isNotEmpty) }
    .associate {
        it.first().replace("[\\[\\]]".toRegex(), "") to it.takeLast(it.size-1)
    }
  • Related