如何在Kotlin中无限重复序列?

Eri*_*rik 10 collections sequence kotlin

我想无限重复一个T元素Sequence<T>.使用kotlin.collections.asSequence无法完成此操作.例如:

val intArray = intArrayOf(1, 2, 3)
val finiteIntSequence = intArray.asSequence()
val many = 10
finiteIntSequence.take(many).forEach(::print)
// 123
Run Code Online (Sandbox Code Playgroud)

这不是我想要的.我期望某种kotlin.collections.repeat功能存在,但没有,所以我自己实现了一个(例如为此IntArray):

var i = 0
val infiniteIntSequence = generateSequence { intArray[i++ % intArray.size] }
infiniteIntSequence.take(many).forEach(::print)
// 1231231231
Run Code Online (Sandbox Code Playgroud)

这是非常必要的,所以我觉得必须有一个更实用,更简洁的方法来做到这一点.如果它存在,Kotlin的标准方式是重复集合/数组a(n)(in)有限次数是什么?

Moi*_*ira 12

更新:从Kotlin 1.3开始,协同程序不再具有实验性!尽可能多地使用它们:)


如果允许使用协同程序,则可以使用sequence以下方式以非常干净的方式执行此操作:

无限次

fun <T> Sequence<T>.repeat() = sequence { while (true) yieldAll(this@repeat) }
Run Code Online (Sandbox Code Playgroud)

注意使用限定this表达式 this@repeat - 简单地使用this将引用lambda的接收器,a SequenceScope.

那么你可以做到

val intArray = intArrayOf(1, 2, 3)
val finiteIntSequence = intArray.asSequence()
val infiniteIntSequence = finiteIntSequence.repeat()

println(infiniteIntSequence.take(10).toList())
// ^ [1, 2, 3, 1, 2, 3, 1, 2, 3, 1]
Run Code Online (Sandbox Code Playgroud)

有限的次数

fun <T> Sequence<T>.repeat(n: Int) = sequence { repeat(n) { yieldAll(this@repeat) } }
Run Code Online (Sandbox Code Playgroud)

  • @voddan谢谢,这绝对是更清洁,可以说更具可读性:) (2认同)

Eri*_*rik 5

为避免使用实验性协程,请使用:

generateSequence { setOf("foo", 'b', 'a', 'r') }
  .flatten() // Put the Iterables' contents into one Sequence
  .take(5) // Take 5 elements
  .joinToString(", ")

// Result: "foo, b, a, r, foo"
Run Code Online (Sandbox Code Playgroud)

或者,如果您想多次重复整个集合,只需在展平之前进行:

generateSequence { setOf("foo", 'b', 'a', 'r') }
  .take(5) // Take the entire Iterable 5 times
  .flatten() // Put the Iterables' contents into one Sequence
  .joinToString(", ")

// Result: "foo, b, a, r, foo, b, a, r, foo, b, a, r, foo, b, a, r, foo, b, a, r"
Run Code Online (Sandbox Code Playgroud)

对于原始问题的IntArray,必须首先将数组转换为一个Iterable<Int>(否则flatten()不可用):

val intArray = intArrayOf(1, 2, 3)

generateSequence { intArray.asIterable() }
  .flatten()
  .take(10)
  .joinToString(", ")

// Result: "1, 2, 3, 1, 2, 3, 1, 2, 3, 1"
Run Code Online (Sandbox Code Playgroud)

此外,其他类型的Array,例如ByteArrayLongArray,以及Map不是Iterable,但它们都实现了上面示例中的asIterable()方法IntArray