I have a List
of objects I want to split by a delimiter into sublists, e.g:
val tokens = listOf(
Token(name = "lorem", val = "ipsum"),
Token(name = "dolor", val = "sit"),
Token(name = "newline", val = "\n"),
Token(name = "amet", val = "consectetur")
)
The delimiter should be any Token
whose name
is "newline"
, so after the split, tokens
should become:
listOf(
listOf(
Token(name = "lorem", val = "ipsum"),
Token(name = "dolor", val = "sit")
),
listOf(
Token(name = "amet", val = "consectetur")
)
)
I've written my own function to do this already, but I was wondering if there was some elegant, built-in (preferably functional) way of doing it. I say this because I'm learning Kotlin and, coming from C , find myself "reinventing the wheel" a lot with these types of things.
CodePudding user response:
I think there isn't any extension function in standard library for handling this case. You will have to write your own logic. You can do something like this:
val newList = mutableListOf<List<Token>>()
var subList = mutableListOf<Token>()
for (token in tokens) {
if (token.name == "newline") {
newList = subList
subList = mutableListOf()
} else {
subList = token
}
}
if (subList.isNotEmpty())
newList = subList
println(newList)
You can also extract this code out in the form of an extension function:
fun <T> List<T>.split(delimiter: (T) -> Boolean): List<List<T>> {
val newList = mutableListOf<List<T>>()
var subList = mutableListOf<T>()
for (token in this) {
if (delimiter(token)) {
newList = subList
subList = mutableListOf()
} else {
subList = token
}
}
if (subList.isNotEmpty())
newList = subList
return newList
}
// Usage
fun main() {
val tokens = listOf(
Token(name = "lorem", val = "ipsum"),
Token(name = "dolor", val = "sit"),
Token(name = "newline", val = "\n"),
Token(name = "amet", val = "consectetur")
)
println(tokens.split { it.name == "newline" })
}
CodePudding user response:
You can use fold
:
tokens
.fold(mutableListOf(mutableListOf<Token>())) { l, elem ->
if(elem.name=="newline") l.add(mutableListOf())
else l.last().add(elem)
l
}
The first parameter is the initial value, a list with a single list in it (If there is no newline, you still want to have a single list containing the elements).
The second parameter is a function that is ececuted for every element.
If the token name is newline
, it adds a new list. If not, it adds the element to the last list.
The last line of fold
containing l
makes sure that the list is returned.