#kotlin
Вопрос:
Я хочу, чтобы функция возвращала новый список с новым значением без изменения исходного списка
fun <T> change(list:List<T>,index:Int,value:T){
}
экзамен в машинописном виде
function change<T>(array:T[],index:number,value:T){
return [...array.slice(0,index),value,...array.slice(index 1)]
}
Комментарии:
1. Вы хотите вернуть новый список без изменения значений исходного
Ответ №1:
Аналогичный подход к коду скрипта вашего типа был бы:
fun <T> List<T>.with(element: T, atIndex: Int) =
subList(0, atIndex) element subList(atIndex 1, size)
или
fun <T> List<T>.with(element: T, atIndex: Int) =
take(atIndex) element drop(atIndex 1)
Использование:
val list = listOf(1,2,3,4,5)
println(list.with(10, atIndex = 2))
Обратите внимание, что это создает много временных списков, которые могут быть нежелательными (я не знаю, делает ли это код машинописи). Если вы этого не хотите, вы можете просто создать изменяемый список и добавить в него что-то ( subList
возвращает только представление списка и не создает ничего нового).:
fun <T> List<T>.with(element: T, atIndex: Int) =
ArrayList<T>(size).apply {
addAll(this@with.subList(0, atIndex))
add(element)
addAll(this@with.subList(atIndex 1, this@with.size))
}
Или вы можете использовать экспериментальный API buildList
@OptIn(ExperimentalStdlibApi::class)
fun <T> List<T>.with(element: T, atIndex: Int) =
buildList(size) {
addAll(this@with.subList(0, atIndex))
add(element)
addAll(this@with.subList(atIndex 1, this@with.size))
}
Ответ №2:
Если вы не хотите использовать постоянные коллекции, как предлагает @broot, вы можете просто использовать mapIndexed
значение O(n):
fun <T> List<T>.change(index: Int, value: T): List<T> =
mapIndexed { i, originalValue -> if (index == i) value else originalValue }
Ответ №3:
Добавив ответ @Sweeper, вы также можете рассмотреть возможность использования постоянных коллекций. Если вам нужно часто выполнять такие операции, постоянные коллекции могут быть гораздо более производительными как с точки зрения процессора, так и с точки зрения памяти, избегая копирования данных. Проще говоря, они создают новую коллекцию, сохраняя ссылку на исходную и «запоминая» модификацию, чтобы применить ее на лету.
Существует по крайней мере одна реализация постоянных коллекций для Kotlin, предоставленная самой командой Kotlin: https://github.com/Kotlin/kotlinx.collections.immutable . Вы можете использовать его вот так:
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]