如何在Kotlin中无限懒惰地循环列表?

arn*_*nab 3 clojure lazy-sequences kotlin

我有一个列表,directions并希望在我向右或向左转弯时找到下一个方向.这是我的工作代码:

enum class Turn { R, L }
enum class Direction { N, E, S, W }
val directionsInRightTurnOrder = listOf(Direction.N, Direction.E, Direction.S, Direction.W)

private fun calculateNextHeading(heading: Direction, turn: Turn): Direction {
    val currentIndex = directionsInRightTurnOrder.indexOf(heading)
    var nextIndex = currentIndex + if (turn == Turn.R) 1 else -1
    if (nextIndex >= directionsInRightTurnOrder.size)
        nextIndex = directionsInRightTurnOrder.size - nextIndex
    if (nextIndex < 0)
        nextIndex += directionsInRightTurnOrder.size

    return directionsInRightTurnOrder.get(nextIndex)
}
Run Code Online (Sandbox Code Playgroud)
  1. 但是,如果我可以获取directionsInRightTurnOrder列表并无限地(并且懒洋洋地)遍历它,那么这将更加简单和易于阅读.在Clojure中,我可以使用clojure.core/cycle来做到这一点:
(take 5 (cycle ["a" "b"]))
# ("a" "b" "a" "b" "a")
Run Code Online (Sandbox Code Playgroud)
  1. 另一件有用的事情是,如果我可以使用负索引查找列表,比如在Ruby或Python中:

题:

  • 我可以cycle通过Kotlin的列表/收藏吗?
  • 在Kotlin中是否有一种惯用的方法来进行负索引查找?

dan*_*neu 7

这是cycle:

fun <T : Any> cycle(vararg xs: T): Sequence<T> {
    var i = 0
    return generateSequence { xs[i++ % xs.size] }
}

cycle("a", "b").take(5).toList() // ["a", "b", "a", "b", "a"]
Run Code Online (Sandbox Code Playgroud)

以下是如何实现转弯应用程序:

enum class Turn(val step: Int) { L(-1), R(1) }

enum class Direction {
    N, E, S, W;

    fun turned(turn: Turn): Direction {
        val mod: (Int, Int) -> Int = { n, d -> ((n % d) + d) % d }
        return values()[mod(values().indexOf(this) + turn.step, values().size)]
    }
}
Run Code Online (Sandbox Code Playgroud)

听起来就像modulo你正在寻找的 - 负面指数环绕.无法在Kotlin的stdlib中找到它,所以我带了自己的.

Direction.N
    .turned(Turn.R) // E
    .turned(Turn.R) // S
    .turned(Turn.R) // W
    .turned(Turn.R) // N
    .turned(Turn.L) // W
Run Code Online (Sandbox Code Playgroud)

Enum#values()Enum#valueOf(_)在什么让你编程方式访问一个枚举的成员.


Ily*_*lya 6

无限重复给定序列或列表的自定义序列可以很容易地编写为flatten

fun <T> Sequence<T>.repeatIndefinitely(): Sequence<T> = 
    generateSequence(this) { this }.flatten()

fun <T> List<T>.repeatIndefinitely(): Sequence<T> =
    this.asSequence().repeatIndefinitely()
Run Code Online (Sandbox Code Playgroud)