Reputation: 499
I want function return new list with the new value without mutate the original list
fun <T> change(list:List<T>,index:Int,value:T){
}
examble in typescript
function change<T>(array:T[],index:number,value:T){
return [...array.slice(0,index),value,...array.slice(index + 1)]
}
Upvotes: 1
Views: 199
Reputation: 2842
If you don't want to use persistent collections as @broot is suggesting, you can just use mapIndexed
which is O(n):
fun <T> List<T>.change(index: Int, value: T): List<T> =
mapIndexed { i, originalValue -> if (index == i) value else originalValue }
Upvotes: 2
Reputation: 28402
Adding to @Sweeper answer, you can also consider using persistent collections. If you need to perform such operations frequently, persistent collections could be much more performant approach both CPU- and memory-wise, by avoiding the data copying. In simple words, they create a new collection by keeping a reference to the original one and "remembering" the modification to apply it on the fly.
There is at least one implementation of persistent collections for Kotlin, provided by the Kotlin team themselves: https://github.com/Kotlin/kotlinx.collections.immutable . You can use it like this:
val list1 = persistentListOf(1, 2, 3, 4, 5)
val list2 = list1.set(2, 8)
println(list1) // [1, 2, 3, 4, 5]
println(list2) // [1, 2, 8, 4, 5]
Upvotes: 0
Reputation: 272725
A similar approach to your Type Script code would be:
fun <T> List<T>.with(element: T, atIndex: Int) =
subList(0, atIndex) + element + subList(atIndex + 1, size)
or
fun <T> List<T>.with(element: T, atIndex: Int) =
take(atIndex) + element + drop(atIndex + 1)
Usage:
val list = listOf(1,2,3,4,5)
println(list.with(10, atIndex = 2))
Note that this creates many temporary lists, which may be undesirable (I don't know if the TypeScript code also does that). If you don't want that, you can just create a mutable list, and add things to it (subList
returns only a view of the list, and doesn't create anything new):
fun <T> List<T>.with(element: T, atIndex: Int) =
ArrayList<T>(size).apply {
addAll([email protected](0, atIndex))
add(element)
addAll([email protected](atIndex + 1, [email protected]))
}
Or you can use the experimental API buildList
@OptIn(ExperimentalStdlibApi::class)
fun <T> List<T>.with(element: T, atIndex: Int) =
buildList(size) {
addAll([email protected](0, atIndex))
add(element)
addAll([email protected](atIndex + 1, [email protected]))
}
Upvotes: 3