Stdlib: Add iteration over unary function, implement iterator zip and skip

This commit is contained in:
Alexey Sedunov
2013-11-18 13:58:35 +04:00
parent 3fadff21cb
commit 9839c2b0b6
3 changed files with 80 additions and 0 deletions
+65
View File
@@ -2,6 +2,7 @@ package kotlin
import kotlin.support.*
import java.util.Collections
import kotlin.test.assertTrue
/**
* Returns an iterator which invokes the function to calculate the next value on each iteration until the function returns *null*
@@ -10,6 +11,23 @@ public inline fun <T:Any> iterate(nextFunction: () -> T?) : Iterator<T> {
return FunctionIterator(nextFunction)
}
/**
* Returns an iterator which invokes the function to calculate the next value based on the previous one on each iteration
* until the function returns *null*
*/
public inline fun <T: Any> iterate(initialValue: T, nextFunction: (T) -> T?): Iterator<T> =
iterate(nextFunction.toGenerator(initialValue))
/**
* Returns an iterator whose values are pairs composed of values produced by given pair of iterators
*/
public inline fun <T, S> Iterator<T>.zip(iterator: Iterator<S>): Iterator<Pair<T, S>> = PairIterator(this, iterator)
/**
* Returns an iterator shifted to right by the given number of elements
*/
public inline fun <T> Iterator<T>.skip(n: Int): Iterator<T> = SkippingIterator(this, n)
class FilterIterator<T>(val iterator : Iterator<T>, val predicate: (T)-> Boolean) : AbstractIterator<T>() {
override protected fun computeNext(): Unit {
while (iterator.hasNext()) {
@@ -147,3 +165,50 @@ class IndexIterator<T>(val iterator : Iterator<T>): Iterator<Pair<Int, T>> {
return iterator.hasNext()
}
}
public class PairIterator<T, S>(
val iterator1 : Iterator<T>, val iterator2 : Iterator<S>
): AbstractIterator<Pair<T, S>>() {
protected override fun computeNext() {
if (iterator1.hasNext() && iterator2.hasNext()) {
setNext(Pair(iterator1.next(), iterator2.next()))
}
else {
done()
}
}
}
class SkippingIterator<T>(val iterator: Iterator<T>, val n: Int): Iterator<T> {
private var firstTime: Boolean = true
private fun skip() {
for (i in 1..n) {
if (!iterator.hasNext()) break
iterator.next()
}
firstTime = false
}
override fun next(): T {
assertTrue(!firstTime, "hasNext() must be invoked before advancing an iterator")
return iterator.next()
}
override fun hasNext(): Boolean {
if (firstTime) {
skip()
}
return iterator.hasNext()
}
}
fun <T: Any> Function1<T, T?>.toGenerator(initialValue: T): Function0<T?> {
var nextValue: T? = initialValue
return {
nextValue?.let { result ->
nextValue = this@toGenerator(result)
result
}
}
}
@@ -18,4 +18,9 @@ class FunctionIteratorTest {
val list = iter.toList()
assertEquals(arrayList(2, 1, 0), list)
}
Test fun iterateOverFunction2() {
val values = iterate<Int>(3) { n -> if (n > 0) n - 1 else null }
assertEquals(arrayList(3, 2, 1, 0), values.toList())
}
}
@@ -77,4 +77,14 @@ class IteratorsTest {
assertEquals("13, 21, 34, 55, 89, 144, 233, 377, 610, 987, ...", fibonacci().filter { it > 10 }.makeString(limit = 10))
assertEquals("144, 233, 377, 610, 987", fibonacci().filter { it > 100 }.takeWhile { it < 1000 }.makeString())
}
test fun pairIterator() {
val pairStr = (fibonacci() zip fibonacci().map { i -> i*2 }).makeString(limit = 10)
assertEquals("(0, 0), (1, 2), (1, 2), (2, 4), (3, 6), (5, 10), (8, 16), (13, 26), (21, 42), (34, 68), ...", pairStr)
}
test fun skippingIterator() {
assertEquals("13, 21, 34, 55, 89, 144, 233, 377, 610, 987, ...", fibonacci().skip(7).makeString(limit = 10))
assertEquals("13, 21, 34, 55, 89, 144, 233, 377, 610, 987, ...", fibonacci().skip(3).skip(4).makeString(limit = 10))
}
}