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