Reputation: 2086
Let's say I want to do the following:
val (k, v) = pair.split("=".toRegex(), 2)
This code is fine if I always get 2 components from the split - however, if the delimiter is not present in the string, this code throws an exception, because the second element in the array isn't present.
The answer is almost certainly "no", but is there some way to coerce destructure to assign null values to missing components?
Upvotes: 10
Views: 2248
Reputation: 5834
It doesn't cover as many cases as other answers (also might not be as obvious what's happening) but you can always force there to be at least the correct number of values to destructure (extra values will be ignored). Using your example you can just add null
to increase the size of the list returned by split
:
val (k, v) = "foo=bar".split("=".toRegex(), 2) + null
> k=foo, v=bar
val (k, v) = "foo".split("=".toRegex(), 2) + null
> k=foo, v=null
Playground example https://pl.kotl.in/W7gGYyAjC
Upvotes: 0
Reputation: 1926
When destructuring objects, Kotlin calls componentN()
for that object. For arrays, component1()
is equal to get(0)
, component2()
is equal to get(1)
, and so on.
So if the index is out of bounds, it'll throw ArrayIndexOutOfBoundsException
, instead of returning null
.
But you can make your operator function like this:
operator fun <T> Array<out T>.component1(): T? = if (size > 0) get(0) else null
operator fun <T> Array<out T>.component2(): T? = if (size > 1) get(1) else null
so if I run
val (k, v) = arrayOf(1)
println(k)
println(v)
the output will be
1
null
See:
Upvotes: 9
Reputation: 89608
You could add your own extension to List
that adds the required number of null
values to the end:
val (k, v) = pair.split("=".toRegex(), 2).padWithNulls(limit = 2)
Implementation can be done a couple of ways, here's just one:
private inline fun <reified E> List<E>.padWithNulls(limit: Int): List<E?> {
if (this.size >= limit) {
return this
}
val result: MutableList<E?> = this.toMutableList()
result.addAll(arrayOfNulls(limit - this.size))
return result
}
Here's a simpler one as well:
private fun <E> List<E>.padWithNulls(limit: Int): List<E?> {
val result: MutableList<E?> = this.toMutableList()
while (result.size < limit) {
result.add(null)
}
return result
}
Or wrapping this functionality even further:
val (k, v) = pair.splitAndPadWithNulls("=".toRegex(), 2)
private fun String.splitAndPadWithNulls(regex: Regex, limit: Int): List<String?> {
return this.split(regex, limit).padWithNulls(limit)
}
Upvotes: 3
Reputation: 13348
Its working for me
val pair="your string"
if(pair.isNotEmpty()&&pair.contains("=")) {
val (k, v) = pair.split("=".toRegex(), 2)
println(k)
println(v)
}
Upvotes: 0