What is the best way to “replace” an element of an immutable list?
I came up with the following ugly solution:
val list = listOf(1, 2, 3)
val updatedList = listOf(99, *(list.subList(1, list.size).toTypedArray()))
However, despite being a bit noisy it would get even worse if you want to replace an element in the middle of the list. If I’m not overlooking something, I think Kotlin needs some more methods like the updated and patch methods of Scala’s List type.
My example would look like this in Scala:
val list = List(1, 2, 3)
val updatedList = list.updated(0, 99)
Well firstly you could think about using a mutable list. Also listOf does give you a mutable implementation hidden behind a readonly interface, so you could cast it (in most situations).
Otherwise I would use mapIndexed and update the list that way.
I don’t think it is good idea to cast immutable list to mutable since it breaks the contract and is not guaranteed to work. The correct way is to either use mutableListOf from the beginning or create mutable copy via toMutableList extension.
Not sure if it’s a douche move to revive this topic – if so, then I apologize – but in the interest of helping anyone still looking for a solution to this issue, I’ll give it a go:
My take on this was a function that took a new value and a lambda, and returned a new list where the elements for which the lambda returned true were replaced:
fun <T> List<T>.replace(newValue: T, block: (T) -> Boolean): List<T> {
return map {
if (block(it)) newValue else it
}
}
On replacing 1 with 99 in the sample:
val list = listOf(1, 2, 3)
val updatedList = list.replace(newValue = 99) { it == 1 }
This would of course replace every insteance of 1, but could also be complemented with a similar replaceFirst or replaceLast function as well.
Hope this helps anyone looking for a similar solution!