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

我想在一个Sequence无限重复T元素。 这不能使用kotlin.collections.asSequence完成。 例如:

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

这不是我想要的。 我期望某种types的kotlin.collections.repeat函数存在,但没有,所以我自己实现了一个(例如对于这个IntArray ):

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

这是非常必要的,所以我觉得必须有一个更实用,更不详细的方法来做到这一点。 如果存在的话,那么Kotlin的标准方法是什么?重复收集/排列a(n)(in)有限的时间?

如果你允许使用协程,你可以用一个非常干净的方式使用buildSequence来做到这buildSequence

无限的时间

 fun  Sequence.repeat() = buildSequence { while (true) yieldAll(this@repeat) } 

注意使用限定的thisexpression式 this@repeat – 简单地使用this就是指lambda的接收器,一个SequenceBuilder

那么你可以做

 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] 

有限的时间

 fun  Sequence.repeat(n: Int) = buildSequence { repeat(n) { yieldAll(this@repeat) } } 

请注意,使用协程会导致一个警告,因为他们是实验,如果你没有“启用”他们在Maven / Gradle /等。

我认为这很清楚:

 generateSequence(0) { (it + 1) % intArray.size } .map { intArray[it] } .forEach { println(it) } 

一个通用的解决方案将是重用这个答案的提案与扩展function:

 fun  Array.asRepeatedSequence() = generateSequence(0) { (it + 1) % this.size }.map(::get) fun  List.asRepeatedSequence() = generateSequence(0) { (it + 1) % this.size }.map(::get) 

这样调用:

 intArray.asRepeatedSequence().forEach(::println) 

为了避免使用实验协同程序,请使用:

 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" 

或者,如果您想多次重复整个收集,请在平整之前进行:

 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" 

对于原始问题的IntArray ,首先必须将数组转换为Iterable (否则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" 

此外,其他types的Array ,例如ByteArrayLongArray以及Map也不是可以asIterable() ,但是在上面的例子中它们都实现了像IntArray这样的asIterable()方法。