Deprecate withIndicies(), introduce optimized and fixed withIndex and forEachIndexed()

This commit is contained in:
Ilya Ryzhenkov
2014-11-06 20:35:33 +03:00
parent b5fb09b8bc
commit e890c2ee0d
8 changed files with 273 additions and 6 deletions
@@ -869,6 +869,102 @@ public inline fun String.forEach(operation: (Char) -> Unit): Unit {
for (element in this) operation(element)
}
/**
* Performs the given *operation* on each element, providing sequential index with the element
*/
public inline fun <T> Array<out T>.forEachIndexed(operation: (Int, T) -> Unit): Unit {
var index = 0
for (item in this) operation(index++, item)
}
/**
* Performs the given *operation* on each element, providing sequential index with the element
*/
public inline fun BooleanArray.forEachIndexed(operation: (Int, Boolean) -> Unit): Unit {
var index = 0
for (item in this) operation(index++, item)
}
/**
* Performs the given *operation* on each element, providing sequential index with the element
*/
public inline fun ByteArray.forEachIndexed(operation: (Int, Byte) -> Unit): Unit {
var index = 0
for (item in this) operation(index++, item)
}
/**
* Performs the given *operation* on each element, providing sequential index with the element
*/
public inline fun CharArray.forEachIndexed(operation: (Int, Char) -> Unit): Unit {
var index = 0
for (item in this) operation(index++, item)
}
/**
* Performs the given *operation* on each element, providing sequential index with the element
*/
public inline fun DoubleArray.forEachIndexed(operation: (Int, Double) -> Unit): Unit {
var index = 0
for (item in this) operation(index++, item)
}
/**
* Performs the given *operation* on each element, providing sequential index with the element
*/
public inline fun FloatArray.forEachIndexed(operation: (Int, Float) -> Unit): Unit {
var index = 0
for (item in this) operation(index++, item)
}
/**
* Performs the given *operation* on each element, providing sequential index with the element
*/
public inline fun IntArray.forEachIndexed(operation: (Int, Int) -> Unit): Unit {
var index = 0
for (item in this) operation(index++, item)
}
/**
* Performs the given *operation* on each element, providing sequential index with the element
*/
public inline fun LongArray.forEachIndexed(operation: (Int, Long) -> Unit): Unit {
var index = 0
for (item in this) operation(index++, item)
}
/**
* Performs the given *operation* on each element, providing sequential index with the element
*/
public inline fun ShortArray.forEachIndexed(operation: (Int, Short) -> Unit): Unit {
var index = 0
for (item in this) operation(index++, item)
}
/**
* Performs the given *operation* on each element, providing sequential index with the element
*/
public inline fun <T> Iterable<T>.forEachIndexed(operation: (Int, T) -> Unit): Unit {
var index = 0
for (item in this) operation(index++, item)
}
/**
* Performs the given *operation* on each element, providing sequential index with the element
*/
public inline fun <T> Stream<T>.forEachIndexed(operation: (Int, T) -> Unit): Unit {
var index = 0
for (item in this) operation(index++, item)
}
/**
* Performs the given *operation* on each element, providing sequential index with the element
*/
public inline fun String.forEachIndexed(operation: (Int, Char) -> Unit): Unit {
var index = 0
for (item in this) operation(index++, item)
}
/**
* Returns the largest element or null if there are no elements
*/
@@ -750,9 +750,94 @@ public inline fun <R, C : MutableCollection<in R>> String.mapTo(destination: C,
return destination
}
/**
* Returns a lazy [Iterable] of [IndexedValue] for each element of the original collection
*/
public fun <T> Array<out T>.withIndex(): Iterable<IndexedValue<T>> {
return IndexingIterable { iterator() }
}
/**
* Returns a lazy [Iterable] of [IndexedValue] for each element of the original collection
*/
public fun BooleanArray.withIndex(): Iterable<IndexedValue<Boolean>> {
return IndexingIterable { iterator() }
}
/**
* Returns a lazy [Iterable] of [IndexedValue] for each element of the original collection
*/
public fun ByteArray.withIndex(): Iterable<IndexedValue<Byte>> {
return IndexingIterable { iterator() }
}
/**
* Returns a lazy [Iterable] of [IndexedValue] for each element of the original collection
*/
public fun CharArray.withIndex(): Iterable<IndexedValue<Char>> {
return IndexingIterable { iterator() }
}
/**
* Returns a lazy [Iterable] of [IndexedValue] for each element of the original collection
*/
public fun DoubleArray.withIndex(): Iterable<IndexedValue<Double>> {
return IndexingIterable { iterator() }
}
/**
* Returns a lazy [Iterable] of [IndexedValue] for each element of the original collection
*/
public fun FloatArray.withIndex(): Iterable<IndexedValue<Float>> {
return IndexingIterable { iterator() }
}
/**
* Returns a lazy [Iterable] of [IndexedValue] for each element of the original collection
*/
public fun IntArray.withIndex(): Iterable<IndexedValue<Int>> {
return IndexingIterable { iterator() }
}
/**
* Returns a lazy [Iterable] of [IndexedValue] for each element of the original collection
*/
public fun LongArray.withIndex(): Iterable<IndexedValue<Long>> {
return IndexingIterable { iterator() }
}
/**
* Returns a lazy [Iterable] of [IndexedValue] for each element of the original collection
*/
public fun ShortArray.withIndex(): Iterable<IndexedValue<Short>> {
return IndexingIterable { iterator() }
}
/**
* Returns a lazy [Iterable] of [IndexedValue] for each element of the original collection
*/
public fun <T> Iterable<T>.withIndex(): Iterable<IndexedValue<T>> {
return IndexingIterable { iterator() }
}
/**
* Returns a stream of [IndexedValue] for each element of the original stream
*/
public fun <T> Stream<T>.withIndex(): Stream<IndexedValue<T>> {
return IndexingStream(this)
}
/**
* Returns a lazy [Iterable] of [IndexedValue] for each element of the original collection
*/
public fun String.withIndex(): Iterable<IndexedValue<Char>> {
return IndexingIterable { iterator() }
}
/**
* Returns a list containing pairs of each element of the original collection and their index
*/
deprecated("Use withIndex() instead.")
public fun <T> Array<out T>.withIndices(): List<Pair<Int, T>> {
var index = 0
return mapTo(ArrayList<Pair<Int, T>>(), { index++ to it })
@@ -761,6 +846,7 @@ public fun <T> Array<out T>.withIndices(): List<Pair<Int, T>> {
/**
* Returns a list containing pairs of each element of the original collection and their index
*/
deprecated("Use withIndex() instead.")
public fun BooleanArray.withIndices(): List<Pair<Int, Boolean>> {
var index = 0
return mapTo(ArrayList<Pair<Int, Boolean>>(), { index++ to it })
@@ -769,6 +855,7 @@ public fun BooleanArray.withIndices(): List<Pair<Int, Boolean>> {
/**
* Returns a list containing pairs of each element of the original collection and their index
*/
deprecated("Use withIndex() instead.")
public fun ByteArray.withIndices(): List<Pair<Int, Byte>> {
var index = 0
return mapTo(ArrayList<Pair<Int, Byte>>(), { index++ to it })
@@ -777,6 +864,7 @@ public fun ByteArray.withIndices(): List<Pair<Int, Byte>> {
/**
* Returns a list containing pairs of each element of the original collection and their index
*/
deprecated("Use withIndex() instead.")
public fun CharArray.withIndices(): List<Pair<Int, Char>> {
var index = 0
return mapTo(ArrayList<Pair<Int, Char>>(), { index++ to it })
@@ -785,6 +873,7 @@ public fun CharArray.withIndices(): List<Pair<Int, Char>> {
/**
* Returns a list containing pairs of each element of the original collection and their index
*/
deprecated("Use withIndex() instead.")
public fun DoubleArray.withIndices(): List<Pair<Int, Double>> {
var index = 0
return mapTo(ArrayList<Pair<Int, Double>>(), { index++ to it })
@@ -793,6 +882,7 @@ public fun DoubleArray.withIndices(): List<Pair<Int, Double>> {
/**
* Returns a list containing pairs of each element of the original collection and their index
*/
deprecated("Use withIndex() instead.")
public fun FloatArray.withIndices(): List<Pair<Int, Float>> {
var index = 0
return mapTo(ArrayList<Pair<Int, Float>>(), { index++ to it })
@@ -801,6 +891,7 @@ public fun FloatArray.withIndices(): List<Pair<Int, Float>> {
/**
* Returns a list containing pairs of each element of the original collection and their index
*/
deprecated("Use withIndex() instead.")
public fun IntArray.withIndices(): List<Pair<Int, Int>> {
var index = 0
return mapTo(ArrayList<Pair<Int, Int>>(), { index++ to it })
@@ -809,6 +900,7 @@ public fun IntArray.withIndices(): List<Pair<Int, Int>> {
/**
* Returns a list containing pairs of each element of the original collection and their index
*/
deprecated("Use withIndex() instead.")
public fun LongArray.withIndices(): List<Pair<Int, Long>> {
var index = 0
return mapTo(ArrayList<Pair<Int, Long>>(), { index++ to it })
@@ -817,6 +909,7 @@ public fun LongArray.withIndices(): List<Pair<Int, Long>> {
/**
* Returns a list containing pairs of each element of the original collection and their index
*/
deprecated("Use withIndex() instead.")
public fun ShortArray.withIndices(): List<Pair<Int, Short>> {
var index = 0
return mapTo(ArrayList<Pair<Int, Short>>(), { index++ to it })
@@ -825,6 +918,7 @@ public fun ShortArray.withIndices(): List<Pair<Int, Short>> {
/**
* Returns a list containing pairs of each element of the original collection and their index
*/
deprecated("Use withIndex() instead.")
public fun <T> Iterable<T>.withIndices(): List<Pair<Int, T>> {
var index = 0
return mapTo(ArrayList<Pair<Int, T>>(), { index++ to it })
@@ -833,6 +927,7 @@ public fun <T> Iterable<T>.withIndices(): List<Pair<Int, T>> {
/**
* Returns a stream containing pairs of each element of the original collection and their index
*/
deprecated("Use withIndex() instead.")
public fun <T> Stream<T>.withIndices(): Stream<Pair<Int, T>> {
var index = 0
return TransformingStream(this, { index++ to it })
@@ -841,6 +936,7 @@ public fun <T> Stream<T>.withIndices(): Stream<Pair<Int, T>> {
/**
* Returns a list containing pairs of each element of the original collection and their index
*/
deprecated("Use withIndex() instead.")
public fun String.withIndices(): List<Pair<Int, Char>> {
var index = 0
return mapTo(ArrayList<Pair<Int, Char>>(), { index++ to it })
+2 -4
View File
@@ -35,10 +35,8 @@ public /*inline*/ fun runnable(action: () -> Unit): Runnable {
}
}
deprecated("Use withIndices() followed by forEach {}")
public inline fun <T> List<T>.forEachWithIndex(operation : (Int, T) -> Unit): Unit = withIndices().forEach {
operation(it.first, it.second)
}
deprecated("Use forEachIndexed instead.")
public inline fun <T> List<T>.forEachWithIndex(operation: (Int, T) -> Unit): Unit = forEachIndexed(operation)
deprecated("Function with undefined semantic")
public fun <T> countTo(n: Int): (T) -> Boolean {
@@ -3,9 +3,9 @@ package kotlin
import java.util.Enumeration
/**
Helper to make java.util.Enumeration usable in for
* Helper to make java.util.Enumeration usable in for
*/
public fun <T> Enumeration<T>.iterator(): Iterator<T> = object: Iterator<T> {
public fun <T> Enumeration<T>.iterator(): Iterator<T> = object : Iterator<T> {
override fun hasNext(): Boolean = hasMoreElements()
public override fun next(): T = nextElement()
@@ -15,3 +15,21 @@ public fun <T> Enumeration<T>.iterator(): Iterator<T> = object: Iterator<T> {
* Returns the given iterator itself. This allows to use an instance of iterator in a ranged for-loop
*/
public fun <T> Iterator<T>.iterator(): Iterator<T> = this
/**
* Data class representing a value with an index
*/
public data class IndexedValue<out T>(public val index: Int, public val value: T)
public class IndexingIterable<out T>(private val iteratorFactory: () -> Iterator<T>) : Iterable<IndexedValue<T>> {
override fun iterator(): Iterator<IndexedValue<T>> = IndexingIterator(iteratorFactory())
}
/**
* Iterator transforming original *iterator* into iterator of [IndexedValue], counting index from zero.
*/
public class IndexingIterator<out T>(private val iterator: Iterator<T>) : Iterator<IndexedValue<T>> {
private var index = 0
final override fun hasNext(): Boolean = iterator.hasNext()
final override fun next(): IndexedValue<T> = IndexedValue(index++, iterator.next())
}
@@ -65,6 +65,20 @@ public class TransformingStream<T, R>(private val stream: Stream<T>, private val
}
}
public class IndexingStream<T>(private val stream: Stream<T>) : Stream<IndexedValue<T>> {
override fun iterator(): Iterator<IndexedValue<T>> = object : Iterator<IndexedValue<T>> {
val iterator = stream.iterator()
var index = 0
override fun next(): IndexedValue<T> {
return IndexedValue(index++, iterator.next())
}
override fun hasNext(): Boolean {
return iterator.hasNext()
}
}
}
public class MergingStream<T1, T2, V>(private val stream1: Stream<T1>,
private val stream2: Stream<T2>,
private val transform: (T1, T2) -> V
@@ -163,6 +163,20 @@ abstract class IterableTests<T : Iterable<String>>(val data: T, val empty: T) {
assertEquals(arrayListOf(3, 3), lengths)
}
Test
fun mapIndexed() {
val shortened = data.mapIndexed { (index, value)-> value.substring(0..index) }
assertEquals(2, shortened.size())
assertEquals(arrayListOf("f", "ba"), shortened)
}
Test
fun withIndex() {
val indexed = data.withIndex().map { it.value.substring(0..it.index) }
assertEquals(2, indexed.size())
assertEquals(arrayListOf("f", "ba"), indexed)
}
Test
fun max() {
expect("foo") { data.max() }
@@ -395,5 +395,17 @@ fun aggregates(): List<GenericFunction> {
include(Maps)
}
templates add f("forEachIndexed(operation: (Int, T) -> Unit)") {
inline(true)
doc { "Performs the given *operation* on each element, providing sequential index with the element" }
returns("Unit")
body {
"""
var index = 0
for (item in this) operation(index++, item)
"""
}
}
return templates
}
@@ -6,6 +6,7 @@ fun mapping(): List<GenericFunction> {
val templates = arrayListOf<GenericFunction>()
templates add f("withIndices()") {
deprecate { "Use withIndex() instead." }
doc { "Returns a list containing pairs of each element of the original collection and their index" }
returns("List<Pair<Int, T>>")
body {
@@ -25,6 +26,24 @@ fun mapping(): List<GenericFunction> {
}
}
templates add f("withIndex()") {
doc { "Returns a lazy [Iterable] of [IndexedValue] for each element of the original collection" }
returns("Iterable<IndexedValue<T>>")
body {
"""
return IndexingIterable { iterator() }
"""
}
returns(Streams) { "Stream<IndexedValue<T>>" }
doc(Streams) { "Returns a stream of [IndexedValue] for each element of the original stream" }
body(Streams) {
"""
return IndexingStream(this)
"""
}
}
templates add f("map(transform: (T) -> R)") {
inline(true)