kotlin 将列表分成两个列表

k75qkfdt  于 2023-02-05  发布在  Kotlin
关注(0)|答案(3)|浏览(173)

在Kotlin中,有没有一种简单的方法可以将Double的列表分成两个对的列表?
以这种方式:

[x1, y1, x2, y2, x3, y3] => [(x1, x2), (x2, x3), (x3, x1)], [(y1, y2), (y2, y3), (y3, y1)]

我尝试使用filterIndexedzipWithNext

val x = filterIndexed { index, _ -> index % 2 == 0 }.zipWithNext()
val y = filterIndexed { index, _ -> index % 2 == 1 }.zipWithNext()

但结果是:

[x1, y1, x2, y2, x3, y3] => [(x1, x2), (x2, x3)], [(y1, y2), (y2, y3)]
kt06eoxx

kt06eoxx1#

如果我没有理解错的话,您使用的zipWithNext的问题在于它没有"回绕",也就是说,没有输出最终的(x3,x1)或(y3,y1)对,包含列表的最后一个元素和第一个元素。
您只需声明自己的zipWithNext版本就可以解决这个问题。
你可以这样做:

fun <T> Iterable<T>.zipWithNextAndWrapAround(): List<Pair<T, T>> {
    val zippedWithNext = zipWithNext()
    if (zippedWithNext.isEmpty()) return zippedWithNext
    return zippedWithNext + (zippedWithNext.last().second to zippedWithNext.first().first)
}

或者复制并粘贴到zipWithNext的原始源代码上,并稍微修改一下:

fun <T> Iterable<T>.zipWithNextAndWrapAround(): List<Pair<T, T>> {
    val iterator = iterator()
    if (!iterator.hasNext()) return emptyList()
    val result = mutableListOf<Pair<T, T>>()
    var current = iterator.next()

    // remember what the first element was
    val first = current
    while (iterator.hasNext()) {
        val next = iterator.next()
        result.add(current to next)
        current = next
    }

    // at last, add this pair
    result.add(current to first)
    return result
}

用法:

val x = list.filterIndexed { index, _ -> index % 2 == 0 }.zipWithNextAndWrapAround()
val y = list.filterIndexed { index, _ -> index % 2 == 1 }.zipWithNextAndWrapAround()

注意,这将遍历列表两次,您可以通过编写自己的partition版本partitionIndexed来避免这种情况。
代码可能类似于:

inline fun <T> Iterable<T>.partitionIndexed(predicate: (Int, T) -> Boolean): Pair<List<T>, List<T>> {
    val first = ArrayList<T>()
    val second = ArrayList<T>()
    forEachIndexed { index, element ->
        if (predicate(index, element)) {
            first.add(element)
        } else {
            second.add(element)
        }
    }
    return Pair(first, second)
}

// usage:
val (x, y) = list.partitionIndexed { index, _ -> 
    index % 2 == 0 
}.let { (a, b) ->
    a.zipWithNextAndWrapAround() to b.zipWithNextAndWrapAround()
}
8yparm6h

8yparm6h2#

你可以这样做:

val lst = listOf(1, 2, 3, 4, 5, 6, 7, 8)

val intermediate = lst.chunked(2).map { it[0] to it[1] }.let { it + it[0] }
val x = intermediate.map { it.first }.zipWithNext()
val y = intermediate.map { it.second }.zipWithNext()

println(x) //[(1, 3), (3, 5), (5, 7), (7, 1)]
println(y) //[(2, 4), (4, 6), (6, 8), (8, 2)]
mccptt67

mccptt673#

val input = listOf("x1", "y1", "x2", "y2", "x3", "y3")

val result = list
  .withIndex()
  .groupBy { it.index % 2 }
  .map { entry -> entry.value.map { it.value } }
  .map { (it + it[0]).zipWithNext() }

println(result)

输出:

[[(x1, x2), (x2, x3), (x3, x1)], [(y1, y2), (y2, y3), (y3, y1)]]

相关问题