diff --git a/libraries/stdlib/src/generated/_Aggregates.kt b/libraries/stdlib/src/generated/_Aggregates.kt index 372567d6967..4ffbbef591a 100644 --- a/libraries/stdlib/src/generated/_Aggregates.kt +++ b/libraries/stdlib/src/generated/_Aggregates.kt @@ -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 Array.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 Iterable.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 Stream.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 */ diff --git a/libraries/stdlib/src/generated/_Mapping.kt b/libraries/stdlib/src/generated/_Mapping.kt index b628312aee9..916c948da2d 100644 --- a/libraries/stdlib/src/generated/_Mapping.kt +++ b/libraries/stdlib/src/generated/_Mapping.kt @@ -750,9 +750,94 @@ public inline fun > String.mapTo(destination: C, return destination } +/** + * Returns a lazy [Iterable] of [IndexedValue] for each element of the original collection + */ +public fun Array.withIndex(): Iterable> { + return IndexingIterable { iterator() } +} + +/** + * Returns a lazy [Iterable] of [IndexedValue] for each element of the original collection + */ +public fun BooleanArray.withIndex(): Iterable> { + return IndexingIterable { iterator() } +} + +/** + * Returns a lazy [Iterable] of [IndexedValue] for each element of the original collection + */ +public fun ByteArray.withIndex(): Iterable> { + return IndexingIterable { iterator() } +} + +/** + * Returns a lazy [Iterable] of [IndexedValue] for each element of the original collection + */ +public fun CharArray.withIndex(): Iterable> { + return IndexingIterable { iterator() } +} + +/** + * Returns a lazy [Iterable] of [IndexedValue] for each element of the original collection + */ +public fun DoubleArray.withIndex(): Iterable> { + return IndexingIterable { iterator() } +} + +/** + * Returns a lazy [Iterable] of [IndexedValue] for each element of the original collection + */ +public fun FloatArray.withIndex(): Iterable> { + return IndexingIterable { iterator() } +} + +/** + * Returns a lazy [Iterable] of [IndexedValue] for each element of the original collection + */ +public fun IntArray.withIndex(): Iterable> { + return IndexingIterable { iterator() } +} + +/** + * Returns a lazy [Iterable] of [IndexedValue] for each element of the original collection + */ +public fun LongArray.withIndex(): Iterable> { + return IndexingIterable { iterator() } +} + +/** + * Returns a lazy [Iterable] of [IndexedValue] for each element of the original collection + */ +public fun ShortArray.withIndex(): Iterable> { + return IndexingIterable { iterator() } +} + +/** + * Returns a lazy [Iterable] of [IndexedValue] for each element of the original collection + */ +public fun Iterable.withIndex(): Iterable> { + return IndexingIterable { iterator() } +} + +/** + * Returns a stream of [IndexedValue] for each element of the original stream + */ +public fun Stream.withIndex(): Stream> { + return IndexingStream(this) +} + +/** + * Returns a lazy [Iterable] of [IndexedValue] for each element of the original collection + */ +public fun String.withIndex(): Iterable> { + return IndexingIterable { iterator() } +} + /** * Returns a list containing pairs of each element of the original collection and their index */ +deprecated("Use withIndex() instead.") public fun Array.withIndices(): List> { var index = 0 return mapTo(ArrayList>(), { index++ to it }) @@ -761,6 +846,7 @@ public fun Array.withIndices(): List> { /** * Returns a list containing pairs of each element of the original collection and their index */ +deprecated("Use withIndex() instead.") public fun BooleanArray.withIndices(): List> { var index = 0 return mapTo(ArrayList>(), { index++ to it }) @@ -769,6 +855,7 @@ public fun BooleanArray.withIndices(): List> { /** * Returns a list containing pairs of each element of the original collection and their index */ +deprecated("Use withIndex() instead.") public fun ByteArray.withIndices(): List> { var index = 0 return mapTo(ArrayList>(), { index++ to it }) @@ -777,6 +864,7 @@ public fun ByteArray.withIndices(): List> { /** * Returns a list containing pairs of each element of the original collection and their index */ +deprecated("Use withIndex() instead.") public fun CharArray.withIndices(): List> { var index = 0 return mapTo(ArrayList>(), { index++ to it }) @@ -785,6 +873,7 @@ public fun CharArray.withIndices(): List> { /** * Returns a list containing pairs of each element of the original collection and their index */ +deprecated("Use withIndex() instead.") public fun DoubleArray.withIndices(): List> { var index = 0 return mapTo(ArrayList>(), { index++ to it }) @@ -793,6 +882,7 @@ public fun DoubleArray.withIndices(): List> { /** * Returns a list containing pairs of each element of the original collection and their index */ +deprecated("Use withIndex() instead.") public fun FloatArray.withIndices(): List> { var index = 0 return mapTo(ArrayList>(), { index++ to it }) @@ -801,6 +891,7 @@ public fun FloatArray.withIndices(): List> { /** * Returns a list containing pairs of each element of the original collection and their index */ +deprecated("Use withIndex() instead.") public fun IntArray.withIndices(): List> { var index = 0 return mapTo(ArrayList>(), { index++ to it }) @@ -809,6 +900,7 @@ public fun IntArray.withIndices(): List> { /** * Returns a list containing pairs of each element of the original collection and their index */ +deprecated("Use withIndex() instead.") public fun LongArray.withIndices(): List> { var index = 0 return mapTo(ArrayList>(), { index++ to it }) @@ -817,6 +909,7 @@ public fun LongArray.withIndices(): List> { /** * Returns a list containing pairs of each element of the original collection and their index */ +deprecated("Use withIndex() instead.") public fun ShortArray.withIndices(): List> { var index = 0 return mapTo(ArrayList>(), { index++ to it }) @@ -825,6 +918,7 @@ public fun ShortArray.withIndices(): List> { /** * Returns a list containing pairs of each element of the original collection and their index */ +deprecated("Use withIndex() instead.") public fun Iterable.withIndices(): List> { var index = 0 return mapTo(ArrayList>(), { index++ to it }) @@ -833,6 +927,7 @@ public fun Iterable.withIndices(): List> { /** * Returns a stream containing pairs of each element of the original collection and their index */ +deprecated("Use withIndex() instead.") public fun Stream.withIndices(): Stream> { var index = 0 return TransformingStream(this, { index++ to it }) @@ -841,6 +936,7 @@ public fun Stream.withIndices(): Stream> { /** * Returns a list containing pairs of each element of the original collection and their index */ +deprecated("Use withIndex() instead.") public fun String.withIndices(): List> { var index = 0 return mapTo(ArrayList>(), { index++ to it }) diff --git a/libraries/stdlib/src/kotlin/Deprecated.kt b/libraries/stdlib/src/kotlin/Deprecated.kt index fa84bdaa9a6..e3018d3766a 100644 --- a/libraries/stdlib/src/kotlin/Deprecated.kt +++ b/libraries/stdlib/src/kotlin/Deprecated.kt @@ -35,10 +35,8 @@ public /*inline*/ fun runnable(action: () -> Unit): Runnable { } } -deprecated("Use withIndices() followed by forEach {}") -public inline fun List.forEachWithIndex(operation : (Int, T) -> Unit): Unit = withIndices().forEach { - operation(it.first, it.second) -} +deprecated("Use forEachIndexed instead.") +public inline fun List.forEachWithIndex(operation: (Int, T) -> Unit): Unit = forEachIndexed(operation) deprecated("Function with undefined semantic") public fun countTo(n: Int): (T) -> Boolean { diff --git a/libraries/stdlib/src/kotlin/collections/Iterators.kt b/libraries/stdlib/src/kotlin/collections/Iterators.kt index c64a7b20b9e..ad43902134b 100644 --- a/libraries/stdlib/src/kotlin/collections/Iterators.kt +++ b/libraries/stdlib/src/kotlin/collections/Iterators.kt @@ -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 Enumeration.iterator(): Iterator = object: Iterator { +public fun Enumeration.iterator(): Iterator = object : Iterator { override fun hasNext(): Boolean = hasMoreElements() public override fun next(): T = nextElement() @@ -15,3 +15,21 @@ public fun Enumeration.iterator(): Iterator = object: Iterator { * Returns the given iterator itself. This allows to use an instance of iterator in a ranged for-loop */ public fun Iterator.iterator(): Iterator = this + +/** + * Data class representing a value with an index + */ +public data class IndexedValue(public val index: Int, public val value: T) + +public class IndexingIterable(private val iteratorFactory: () -> Iterator) : Iterable> { + override fun iterator(): Iterator> = IndexingIterator(iteratorFactory()) +} + +/** + * Iterator transforming original *iterator* into iterator of [IndexedValue], counting index from zero. + */ +public class IndexingIterator(private val iterator: Iterator) : Iterator> { + private var index = 0 + final override fun hasNext(): Boolean = iterator.hasNext() + final override fun next(): IndexedValue = IndexedValue(index++, iterator.next()) +} diff --git a/libraries/stdlib/src/kotlin/collections/Stream.kt b/libraries/stdlib/src/kotlin/collections/Stream.kt index 1da1e790ef7..94fc1f14898 100644 --- a/libraries/stdlib/src/kotlin/collections/Stream.kt +++ b/libraries/stdlib/src/kotlin/collections/Stream.kt @@ -65,6 +65,20 @@ public class TransformingStream(private val stream: Stream, private val } } +public class IndexingStream(private val stream: Stream) : Stream> { + override fun iterator(): Iterator> = object : Iterator> { + val iterator = stream.iterator() + var index = 0 + override fun next(): IndexedValue { + return IndexedValue(index++, iterator.next()) + } + + override fun hasNext(): Boolean { + return iterator.hasNext() + } + } +} + public class MergingStream(private val stream1: Stream, private val stream2: Stream, private val transform: (T1, T2) -> V diff --git a/libraries/stdlib/test/collections/IterableTests.kt b/libraries/stdlib/test/collections/IterableTests.kt index dc6ff39d5bb..2dbbf558d71 100644 --- a/libraries/stdlib/test/collections/IterableTests.kt +++ b/libraries/stdlib/test/collections/IterableTests.kt @@ -163,6 +163,20 @@ abstract class IterableTests>(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() } diff --git a/libraries/tools/kotlin-stdlib-gen/src/templates/Aggregates.kt b/libraries/tools/kotlin-stdlib-gen/src/templates/Aggregates.kt index 208cde44757..73a9c8eef0f 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/templates/Aggregates.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/templates/Aggregates.kt @@ -395,5 +395,17 @@ fun aggregates(): List { 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 } \ No newline at end of file diff --git a/libraries/tools/kotlin-stdlib-gen/src/templates/Mapping.kt b/libraries/tools/kotlin-stdlib-gen/src/templates/Mapping.kt index b9d2095f3b5..94746626598 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/templates/Mapping.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/templates/Mapping.kt @@ -6,6 +6,7 @@ fun mapping(): List { val templates = arrayListOf() 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>") body { @@ -25,6 +26,24 @@ fun mapping(): List { } } + templates add f("withIndex()") { + doc { "Returns a lazy [Iterable] of [IndexedValue] for each element of the original collection" } + returns("Iterable>") + body { + """ + return IndexingIterable { iterator() } + """ + } + + returns(Streams) { "Stream>" } + 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)