Существует ли функция сбора, такая как map, чтобы превратить каждый элемент в списке в два элемента?

#kotlin

Вопрос:

Допустим, у меня есть список целых чисел, как таковых:

 val list = listOf(1, 2, 3, 5, 8, 13)
 

Я хочу запустить операцию по созданию аналогичного списка, но с дополнительным элементом после каждого элемента. Например, мы должны иметь возможность добавлять a -99 после каждого элемента как такового:

[1, -99, 2, -99, 3, -99, 5, -99, 8, -99, 13, -99]

Я могу легко сделать это с помощью цикла forEach и временного списка, как такового:

 val list = listOf(1, 2, 3, 5, 8, 13)
val tempList = mutableListOf<Int>()
list.forEach {
    tempList.add(it)
    tempList.add(-99)
}
println(tempList) // [1, -99, 2, -99, 3, -99, 5, -99, 8, -99, 13, -99]
 

Но это кажется излишне многословным и настоятельным. Другой способ, который я нашел, — сопоставить каждый элемент со списком из двух элементов, создать список списков и сгладить результат. Пример:

 val list = listOf(1, 2, 3, 5, 8, 13)
val mapFlatten = list
    .map { listOf(it, -99) }
    .flatten()
 
println(mapFlatten) // [1, -99, 2, -99, 3, -99, 5, -99, 8, -99, 13, -99]
 

Однако создание списка списков, а затем их выравнивание кажется излишне избыточным. Существует ли какая-либо операция со списком, которая позволяет нам сделать это более простым способом?

Ответ №1:

Вы могли бы упростить свой второй вариант, используя flatMap напрямую:

 val list = listOf(1, 2, 3, 5, 8, 13)
val mapFlatten = list.flatMap { listOf(it, -99) }
 

Технически у вас все еще есть эти промежуточные списки, но я не уверен, что их можно упростить дальше.

Если у вас действительно огромные списки и вас беспокоят дополнительные ассигнования, вы можете вернуться к созданию списка вручную, как вы это делали, если только вы не боитесь экспериментальных функций и не согласны с buildList :

 val list = listOf(1, 2, 3, 5, 8, 13)
val mapFlatten = buildList(2 * list.size) {
    list.forEach {
        add(it)
        add(-99)
    }
}
 

Комментарии:

1. размер результирующего списка известен заранее, поэтому для повышения производительности (во избежание перераспределения памяти) его можно указать: buildList(2 * list.size) { ... }

2. @МихаилНафталь TIL buildList can take a capacity. Спасибо!