Как совместить два разных списка длины в kotlin? - PullRequest
0 голосов
/ 28 марта 2019

Я хочу объединить два списка разной длины.Например;

val list1 = listOf(1,2,3,4,5)
val list2 = listOf("a","b","c")

Я хочу получить такой результат

(1,"a",2,"b",3,"c",4,5)

Есть ли какие-либо предложения?

Ответы [ 5 ]

2 голосов
/ 28 марта 2019

Вы можете использовать функцию .zip для этого

list1.zip(list2){ a,b -> listOf(a,b)}.flatten()

Единственная проблема заключается в том, что она будет обрабатывать только элементы с обоими наборами, поэтому если (как в примере) давайте иметь другой размер -это не будет работать

Альтернативой может быть добавление определенных маркеров и их фильтрация или использование для этого итераторов.Я нашел элегантное решение с функцией sequence{..}

 val result = sequence {
    val first = list1.iterator()
    val second = list2.iterator()
    while (first.hasNext() && second.hasNext()) {
      yield(first.next())
      yield(second.next())
    }

    yieldAll(first)
    yieldAll(second)
  }.toList()
1 голос
/ 28 марта 2019

Вы можете сделать это следующим образом:

val mergedList = with(setOf(list1, list2).sortedByDescending { it.count() }) {
    first().mapIndexed { index, e ->
        listOfNotNull(e, last().getOrNull(index))
    }
}.flatten()

Сначала вы помещаете оба списка в Set, а затем сортируете его (по убыванию) по количеству элементов, получающих список списков.

Первый список содержит наибольшее количество элементов, которые будут использоваться для итерации.

Используя mapIndexed, вы можете использовать index для доступа к соответствующему элементу во втором списке.Если его нет, возвращается null, и он будет отфильтрован по listOfNotNull.В итоге вы сгладите получившийся список списков и получите желаемый результат:

[1, a, 2, b, 3, c, 4, 5]

1 голос
/ 28 марта 2019
  1. Если элементы из исходных списков могут находиться в результирующем списке в любом порядке, то
>>> list1 + list2
res12: kotlin.collections.List<kotlin.Any> = [1, 2, 3, 4, 5, a, b, c]
Если элементы из исходных списков должны чередоваться в результирующем списке, а list1 длиннее list2, тогда
>>> list1.zip(list2).flatMap { listOf(it.first, it.second) } + list1.drop(list2.size)
res16: kotlin.collections.List<kotlin.Any> = [1, a, 2, b, 3, c, 4, 5]
0 голосов
/ 29 марта 2019

Я думаю, что ответ Евгения уже содержит все, что вам нужно знать, чтобы объединить два списка (будь то zip или объединить все элементы).

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

fun combine(vararg lists: List<*>) : List<Any> = mutableListOf<Any>().also {
  combine(it, lists.map(List<*>::iterator))
}

private tailrec fun combine(targetList: MutableList<Any>, iterators: List<Iterator<*>>) {
  iterators.asSequence()
          .filter(Iterator<*>::hasNext)
          .mapNotNull(Iterator<*>::next)
          .forEach { targetList += it }
  if (iterators.asSequence().any(Iterator<*>::hasNext))
    combine(targetList, iterators)
}

Затем его вызов выглядит следующим образом и приводит к значению, указанному в комментарии:

combine(list1, list2) // List containing: 1, "a", 2, "b", 3, "c", 4, 5
combine(list1, list2, listOf("hello", "world")) // 1, "a", "hello", 2, "b", "world", 3, "c", 4, 5

Упрощенный подход ко второй части ответа Евгения может быть реализован с использованием следующего кода; это, конечно, больше не лень, когда вы получаете список обратно ;-) (но, возможно, вы даже перевели его прямо в список, так что вы также можете использовать этот подход):

fun List<Any>.combine(other: List<Any>) : List<Any> = mutableListOf<Any>().also {
  val first = iterator()
  val second = other.iterator()
  while (first.hasNext() || second.hasNext()) {
    if (first.hasNext()) it.add(first.next())
    if (second.hasNext()) it.add(second.next())
  }
}

Вызов его будет работать следующим образом:

list1.combine(list2)
0 голосов
/ 28 марта 2019

Ваши списки имеют необратимые типы (Ints и Strings), поэтому вам нужно иметь MutableList<Any>, чтобы вы могли добавить оба типа:

val allItems = mutableListOf<Any>(1,2,3,4,5)
val list2 = listOf("a","b","c")
allItems.addAll(list2)
...