How do I infinitely repeat a sequence in Kotlin?
Update: coroutines are no longer experimental as of Kotlin 1.3! Use them as much as you like :)
If you allow the use of coroutines you can do this in a pretty clean way using sequence
:
an infinite amount of times
fun <T> Sequence<T>.repeat() = sequence { while (true) yieldAll(this@repeat) }
Note the use of a qualified this
expression this@repeat
- simply using this
would refer to the lambda's receiver, a SequenceScope
.
then you can do
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]
a finite amount of times
fun <T> Sequence<T>.repeat(n: Int) = sequence { repeat(n) { yieldAll(this@repeat) } }
To avoid using the experimental coroutines, use:
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"
or alternatively, if you want to repeat the entire collection a number of times, just take before flattening:
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"
For the original question's IntArray
, the array first must be converted to an Iterable<Int>
(otherwise flatten()
isn't available):
val intArray = intArrayOf(1, 2, 3)
generateSequence { intArray.asIterable() }
.flatten()
.take(10)
.joinToString(", ")
// Result: "1, 2, 3, 1, 2, 3, 1, 2, 3, 1"
Furthermore, other types of Array
, e.g. ByteArray
or LongArray
, as well as Map
are not Iterable
, but they all implement the asIterable()
method like IntArray
in the example above.
I think this is pretty clear:
generateSequence(0) { (it + 1) % intArray.size }
.map { intArray[it] }
.forEach { println(it) }