All Downloads are FREE. Search and download functionalities are using the official Maven repository.

kotlin.Iterators.kt Maven / Gradle / Ivy

There is a newer version: 2.1.0-Beta1
Show newest version
package kotlin

import kotlin.support.*
import java.util.Collections
import kotlin.test.assertTrue

/**
 * Returns the given iterator itself. This allows to use an instance of iterator in a ranged for-loop
 */
public fun  Iterator.iterator(): Iterator = this

/**
 * Returns an iterator which invokes the function to calculate the next value on each iteration until the function returns *null*
 */
public fun  iterate(nextFunction: () -> T?) : Iterator {
    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  iterate(initialValue: T, nextFunction: (T) -> T?): Iterator =
        iterate(nextFunction.toGenerator(initialValue))

/**
 * Returns an iterator whose values are pairs composed of values produced by given pair of iterators
 */
public fun  Iterator.zip(iterator: Iterator): Iterator> = PairIterator(this, iterator)

/**
 * Returns an iterator shifted to right by the given number of elements
 */
public fun  Iterator.skip(n: Int): Iterator = SkippingIterator(this, n)

class FilterIterator(val iterator : Iterator, val predicate: (T)-> Boolean) : AbstractIterator() {
    override protected fun computeNext(): Unit {
        while (iterator.hasNext()) {
            val next = iterator.next()
            if ((predicate)(next)) {
                setNext(next)
                return
            }
        }
        done()
    }
}

class FilterNotNullIterator(val iterator : Iterator?) : AbstractIterator() {
    override protected fun computeNext(): Unit {
        if (iterator != null) {
            while (iterator.hasNext()) {
                val next = iterator.next()
                if (next != null) {
                    setNext(next)
                    return
                }
            }
        }
        done()
    }
}

class MapIterator(val iterator : Iterator, val transform: (T) -> R) : AbstractIterator() {
    override protected fun computeNext() : Unit {
        if (iterator.hasNext()) {
            setNext((transform)(iterator.next()))
        } else {
            done()
        }
    }
}

class FlatMapIterator(val iterator : Iterator, val transform: (T) -> Iterator) : AbstractIterator() {
    var transformed: Iterator = iterate { null }

    override protected fun computeNext() : Unit {
        while (true) {
            if (transformed.hasNext()) {
                setNext(transformed.next())
                return
            }
            if (iterator.hasNext()) {
                transformed = (transform)(iterator.next())
            } else {
                done()
                return
            }
        }
    }
}

class TakeWhileIterator(val iterator: Iterator, val predicate: (T) -> Boolean) : AbstractIterator() {
    override protected fun computeNext() : Unit {
        if (iterator.hasNext()) {
            val item = iterator.next()
            if ((predicate)(item)) {
                setNext(item)
                return
            }
        }
        done()
    }
}

/** An [[Iterator]] which invokes a function to calculate the next value in the iteration until the function returns *null* */
class FunctionIterator(val nextFunction: () -> T?): AbstractIterator() {

    override protected fun computeNext(): Unit {
        val next = (nextFunction)()
        if (next == null) {
            done()
        } else {
            setNext(next)
        }
    }
}

/** An [[Iterator]] which iterates over a number of iterators in sequence */
fun CompositeIterator(vararg iterators: Iterator): CompositeIterator = CompositeIterator(iterators.iterator())

class CompositeIterator(val iterators: Iterator>): AbstractIterator() {

    var currentIter: Iterator? = null

    override protected fun computeNext(): Unit {
        while (true) {
            if (currentIter == null) {
                if (iterators.hasNext()) {
                    currentIter = iterators.next()
                } else {
                    done()
                    return
                }
            }
            val iter = currentIter
            if (iter != null) {
                if (iter.hasNext()) {
                    setNext(iter.next())
                    return
                } else {
                    currentIter = null
                }
            }
        }
    }
}

/** A singleton [[Iterator]] which invokes once over a value */
class SingleIterator(val value: T): AbstractIterator() {
    var first = true

    override protected fun computeNext(): Unit {
        if (first) {
            first = false
            setNext(value)
        } else {
            done()
        }
    }
}

class IndexIterator(val iterator : Iterator): Iterator> {
    private var index : Int = 0

    override fun next(): Pair {
        return Pair(index++, iterator.next())
    }

    override fun hasNext(): Boolean {
        return iterator.hasNext()
    }
}

public class PairIterator(
        val iterator1 : Iterator, val iterator2 : Iterator
): AbstractIterator>() {
    protected override fun computeNext() {
        if (iterator1.hasNext() && iterator2.hasNext()) {
            setNext(Pair(iterator1.next(), iterator2.next()))
        }
        else {
            done()
        }
    }
}

class SkippingIterator(val iterator: Iterator, val n: Int): Iterator {
    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()
    }
}

public fun  Function1.toGenerator(initialValue: T): Function0 {
    var nextValue: T? = initialValue
    return {
        nextValue?.let { result ->
            nextValue = this@toGenerator(result)
            result
        }
    }
}