Add Sequence.peekable()

This commit is contained in:
kageru 2019-10-09 12:01:53 +02:00
parent 0aeab3a96b
commit fafefc2820
Signed by: kageru
GPG Key ID: 8282A2BEA4ADA3D2
4 changed files with 71 additions and 1 deletions

View File

@ -0,0 +1,37 @@
package moe.kageru.sekwences
class PeekableSequence<T>(source: Sequence<T>) : Sequence<T> {
private val iterator: PeekableIterator<T> = PeekableIterator(source.iterator())
override fun iterator(): Iterator<T> = iterator
fun peek(): T? = iterator.peek()
}
internal class PeekableIterator<T>(private val source: Iterator<T>) : Iterator<T> {
private var peeked: T? = null
override fun hasNext(): Boolean {
return source.hasNext() || peeked != null
}
override fun next(): T {
return if (peeked == null) {
source.next()
} else {
val ret = peeked
peeked = null
ret!!
}
}
fun peek(): T? {
return when {
peeked != null -> peeked
hasNext() -> {
peeked = next()
peeked!!
}
else -> null
}
}
}

View File

@ -18,3 +18,12 @@ fun <T> Sequence<T>.coalesce(merger: (T, T) -> T?): Sequence<T> {
emptySequence()
}
}
/**
* Modifies the current [Sequence] by adding a peek() method
* that returns the next element or null without advancing the sequence.
* Calling peek() multiple times without next() will return the same value.
*/
fun <T> Sequence<T>.peekable(): PeekableSequence<T> {
return PeekableSequence(this)
}

View File

@ -3,7 +3,7 @@ package moe.kageru.sekwences
import io.kotlintest.shouldBe
import io.kotlintest.specs.ShouldSpec
class SekwencesTest : ShouldSpec({
class CoalesceTest : ShouldSpec({
"should merge numbers" {
val input = sequenceOf(1, 2, 3, 4, 5, 6, 4)
val output = input.coalesce { first, second ->

View File

@ -0,0 +1,24 @@
package moe.kageru.sekwences
import io.kotlintest.shouldBe
import io.kotlintest.specs.ShouldSpec
class PeekableTest : ShouldSpec({
"peek should return correct values" {
val input = sequenceOf(1, 2, 3, 4).peekable()
input.peek() shouldBe 1
input.peek() shouldBe input.peek()
input.iterator().next() shouldBe 1
input.peek() shouldBe 2
input.iterator().next() shouldBe 2
input.iterator().next() shouldBe 3
input.iterator().next() shouldBe 4
input.peek() shouldBe null
}
"sequence should operate normally" {
val input = sequenceOf(1, 2, 3, 4).peekable()
input.peek() shouldBe 1
input.map { it * it }.toList() shouldBe listOf(1, 4, 9, 16)
}
})