我想在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
这不是我想要的。我期望某种kotlin.collections.repeat
函数存在,但是没有,所以我自己实现了一个(例如对于IntArray
):
var i = 0
val infiniteIntSequence = generateSequence { intArray[i++ % intArray.size] }
infiniteIntSequence.take(many).forEach(::print)
// 1231231231
这是非常必要的,所以我觉得必须有一个更实用,更简洁的方法来做到这一点。如果它存在,那么Kotlin的标准方法是重复收集/数组a(n)(in)有限的次数?
答案 0 :(得分:9)
更新:从Kotlin 1.3开始,协同程序不再具有实验性!尽可能多地使用它们:)
如果您允许使用coroutines,则可以使用sequence
以非常干净的方式执行此操作:
无限次
fun <T> Sequence<T>.repeat() = sequence { while (true) yieldAll(this@repeat) }
注意使用qualified this
expression this@repeat
- 只需使用this
即可引用lambda的接收器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]
有限的次数
fun <T> Sequence<T>.repeat(n: Int) = sequence { repeat(n) { yieldAll(this@repeat) } }
答案 1 :(得分:4)
为避免使用实验协同程序,请使用:
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<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"
此外,其他类型的Array
,例如ByteArray
或LongArray
以及Map
不是Iterable
,但它们都在上面的示例中实现asIterable()
方法,如IntArray
。
答案 2 :(得分:1)
我认为这很清楚:
generateSequence(0) { (it + 1) % intArray.size }
.map { intArray[it] }
.forEach { println(it) }
答案 3 :(得分:1)
通用解决方案是重用此answer中包含扩展功能的提案:
fun <T> Array<T>.asRepeatedSequence() =
generateSequence(0) {
(it + 1) % this.size
}.map(::get)
fun <T> List<T>.asRepeatedSequence() =
generateSequence(0) {
(it + 1) % this.size
}.map(::get)
这样称呼:
intArray.asRepeatedSequence().forEach(::println)
答案 4 :(得分:0)
我不确定这是否是由于Kotlin中的API更改引起的,但是可以执行以下操作:
fun <T> Sequence<T>.repeatForever() =
generateSequence(this) { it }.flatten()