From 25cfd36e7c201e7bb24fa7222b896cf833c3200e Mon Sep 17 00:00:00 2001 From: Ilya Gorbunov Date: Tue, 24 Mar 2015 03:33:34 +0300 Subject: [PATCH] drop, take: combine implementations for Collections, Lists and Iterables. slice: predict length of resulting list. --- libraries/stdlib/src/generated/_Filtering.kt | 129 +++++++----------- .../src/templates/Filtering.kt | 63 +++++---- 2 files changed, 88 insertions(+), 104 deletions(-) diff --git a/libraries/stdlib/src/generated/_Filtering.kt b/libraries/stdlib/src/generated/_Filtering.kt index 5e2f230caac..3666e5e9d8d 100644 --- a/libraries/stdlib/src/generated/_Filtering.kt +++ b/libraries/stdlib/src/generated/_Filtering.kt @@ -135,48 +135,34 @@ public fun ShortArray.drop(n: Int): List { return list } -/** - * Returns a list containing all elements except first [n] elements - */ -public fun Collection.drop(n: Int): List { - require(n >= 0, { "Requested element count $n is less than zero." }) - if (n >= size()) - return emptyList() - var count = 0 - val list = ArrayList(size() - n) - for (item in this) { - if (count++ >= n) list.add(item) - } - return list -} - /** * Returns a list containing all elements except first [n] elements */ public fun Iterable.drop(n: Int): List { require(n >= 0, { "Requested element count $n is less than zero." }) + val list: ArrayList + if (this is Collection<*>) { + val resultSize = size() - n + if (resultSize <= 0) + return emptyList() + list = ArrayList(resultSize) + if (this is List) { + for (index in n..size() - 1) { + list.add(this[index]) + } + return list + } + } + else { + list = ArrayList() + } var count = 0 - val list = ArrayList() for (item in this) { if (count++ >= n) list.add(item) } return list } -/** - * Returns a list containing all elements except first [n] elements - */ -public fun List.drop(n: Int): List { - require(n >= 0, { "Requested element count $n is less than zero." }) - if (n >= size()) - return emptyList() - val list = ArrayList(size() - n) - for (index in n..size() - 1) { - list.add(this[index]) - } - return list -} - /** * Returns a sequence containing all elements except first [n] elements */ @@ -858,7 +844,7 @@ public inline fun String.filterTo(destination: C, predicate: (C * Returns a list containing elements at specified positions */ public fun Array.slice(indices: Iterable): List { - val list = ArrayList() + val list = ArrayList(indices.collectionSizeOrDefault(10)) for (index in indices) { list.add(get(index)) } @@ -869,7 +855,7 @@ public fun Array.slice(indices: Iterable): List { * Returns a list containing elements at specified positions */ public fun BooleanArray.slice(indices: Iterable): List { - val list = ArrayList() + val list = ArrayList(indices.collectionSizeOrDefault(10)) for (index in indices) { list.add(get(index)) } @@ -880,7 +866,7 @@ public fun BooleanArray.slice(indices: Iterable): List { * Returns a list containing elements at specified positions */ public fun ByteArray.slice(indices: Iterable): List { - val list = ArrayList() + val list = ArrayList(indices.collectionSizeOrDefault(10)) for (index in indices) { list.add(get(index)) } @@ -891,7 +877,7 @@ public fun ByteArray.slice(indices: Iterable): List { * Returns a list containing elements at specified positions */ public fun CharArray.slice(indices: Iterable): List { - val list = ArrayList() + val list = ArrayList(indices.collectionSizeOrDefault(10)) for (index in indices) { list.add(get(index)) } @@ -902,7 +888,7 @@ public fun CharArray.slice(indices: Iterable): List { * Returns a list containing elements at specified positions */ public fun DoubleArray.slice(indices: Iterable): List { - val list = ArrayList() + val list = ArrayList(indices.collectionSizeOrDefault(10)) for (index in indices) { list.add(get(index)) } @@ -913,7 +899,7 @@ public fun DoubleArray.slice(indices: Iterable): List { * Returns a list containing elements at specified positions */ public fun FloatArray.slice(indices: Iterable): List { - val list = ArrayList() + val list = ArrayList(indices.collectionSizeOrDefault(10)) for (index in indices) { list.add(get(index)) } @@ -924,7 +910,7 @@ public fun FloatArray.slice(indices: Iterable): List { * Returns a list containing elements at specified positions */ public fun IntArray.slice(indices: Iterable): List { - val list = ArrayList() + val list = ArrayList(indices.collectionSizeOrDefault(10)) for (index in indices) { list.add(get(index)) } @@ -935,7 +921,7 @@ public fun IntArray.slice(indices: Iterable): List { * Returns a list containing elements at specified positions */ public fun LongArray.slice(indices: Iterable): List { - val list = ArrayList() + val list = ArrayList(indices.collectionSizeOrDefault(10)) for (index in indices) { list.add(get(index)) } @@ -946,7 +932,7 @@ public fun LongArray.slice(indices: Iterable): List { * Returns a list containing elements at specified positions */ public fun ShortArray.slice(indices: Iterable): List { - val list = ArrayList() + val list = ArrayList(indices.collectionSizeOrDefault(10)) for (index in indices) { list.add(get(index)) } @@ -957,7 +943,7 @@ public fun ShortArray.slice(indices: Iterable): List { * Returns a list containing elements at specified positions */ public fun List.slice(indices: Iterable): List { - val list = ArrayList() + val list = ArrayList(indices.collectionSizeOrDefault(10)) for (index in indices) { list.add(get(index)) } @@ -968,7 +954,7 @@ public fun List.slice(indices: Iterable): List { * Returns a string containing characters at specified positions */ public fun String.slice(indices: Iterable): String { - val result = StringBuilder() + val result = StringBuilder(indices.collectionSizeOrDefault(10)) for (i in indices) { result.append(get(i)) } @@ -981,7 +967,7 @@ public fun String.slice(indices: Iterable): String { public fun Array.take(n: Int): List { require(n >= 0, "Requested element count $n is less than zero.") var count = 0 - val realN = if (n > size()) size() else n + val realN = Math.min(n, size()) val list = ArrayList(realN) for (item in this) { if (count++ == realN) @@ -997,7 +983,7 @@ public fun Array.take(n: Int): List { public fun BooleanArray.take(n: Int): List { require(n >= 0, "Requested element count $n is less than zero.") var count = 0 - val realN = if (n > size()) size() else n + val realN = Math.min(n, size()) val list = ArrayList(realN) for (item in this) { if (count++ == realN) @@ -1013,7 +999,7 @@ public fun BooleanArray.take(n: Int): List { public fun ByteArray.take(n: Int): List { require(n >= 0, "Requested element count $n is less than zero.") var count = 0 - val realN = if (n > size()) size() else n + val realN = Math.min(n, size()) val list = ArrayList(realN) for (item in this) { if (count++ == realN) @@ -1029,7 +1015,7 @@ public fun ByteArray.take(n: Int): List { public fun CharArray.take(n: Int): List { require(n >= 0, "Requested element count $n is less than zero.") var count = 0 - val realN = if (n > size()) size() else n + val realN = Math.min(n, size()) val list = ArrayList(realN) for (item in this) { if (count++ == realN) @@ -1045,7 +1031,7 @@ public fun CharArray.take(n: Int): List { public fun DoubleArray.take(n: Int): List { require(n >= 0, "Requested element count $n is less than zero.") var count = 0 - val realN = if (n > size()) size() else n + val realN = Math.min(n, size()) val list = ArrayList(realN) for (item in this) { if (count++ == realN) @@ -1061,7 +1047,7 @@ public fun DoubleArray.take(n: Int): List { public fun FloatArray.take(n: Int): List { require(n >= 0, "Requested element count $n is less than zero.") var count = 0 - val realN = if (n > size()) size() else n + val realN = Math.min(n, size()) val list = ArrayList(realN) for (item in this) { if (count++ == realN) @@ -1077,7 +1063,7 @@ public fun FloatArray.take(n: Int): List { public fun IntArray.take(n: Int): List { require(n >= 0, "Requested element count $n is less than zero.") var count = 0 - val realN = if (n > size()) size() else n + val realN = Math.min(n, size()) val list = ArrayList(realN) for (item in this) { if (count++ == realN) @@ -1093,7 +1079,7 @@ public fun IntArray.take(n: Int): List { public fun LongArray.take(n: Int): List { require(n >= 0, "Requested element count $n is less than zero.") var count = 0 - val realN = if (n > size()) size() else n + val realN = Math.min(n, size()) val list = ArrayList(realN) for (item in this) { if (count++ == realN) @@ -1109,7 +1095,7 @@ public fun LongArray.take(n: Int): List { public fun ShortArray.take(n: Int): List { require(n >= 0, "Requested element count $n is less than zero.") var count = 0 - val realN = if (n > size()) size() else n + val realN = Math.min(n, size()) val list = ArrayList(realN) for (item in this) { if (count++ == realN) @@ -1119,29 +1105,13 @@ public fun ShortArray.take(n: Int): List { return list } -/** - * Returns a list containing first [n] elements - */ -public fun Collection.take(n: Int): List { - require(n >= 0, "Requested element count $n is less than zero.") - var count = 0 - val realN = if (n > size()) size() else n - val list = ArrayList(realN) - for (item in this) { - if (count++ == realN) - break; - list.add(item) - } - return list -} - /** * Returns a list containing first [n] elements */ public fun Iterable.take(n: Int): List { require(n >= 0, { "Requested element count $n is less than zero." }) var count = 0 - val list = ArrayList(n) + val list = ArrayList(Math.min(n, collectionSizeOrDefault(n))) for (item in this) { if (count++ == n) break @@ -1172,6 +1142,7 @@ public fun Stream.take(n: Int): Stream { * Returns a string containing the first [n] characters from this string, or the entire string if this string is shorter */ public fun String.take(n: Int): String { + require(n >= 0, { "Requested element count $n is less than zero." }) return substring(0, Math.min(n, length())) } @@ -1181,7 +1152,7 @@ public fun String.take(n: Int): String { public fun Array.takeLast(n: Int): List { require(n >= 0, { "Requested element count $n is less than zero." }) val size = size() - val realN = if (n > size) size else n + val realN = Math.min(n, size) val list = ArrayList(realN) for (index in size - realN .. size - 1) list.add(this[index]) @@ -1194,7 +1165,7 @@ public fun Array.takeLast(n: Int): List { public fun BooleanArray.takeLast(n: Int): List { require(n >= 0, { "Requested element count $n is less than zero." }) val size = size() - val realN = if (n > size) size else n + val realN = Math.min(n, size) val list = ArrayList(realN) for (index in size - realN .. size - 1) list.add(this[index]) @@ -1207,7 +1178,7 @@ public fun BooleanArray.takeLast(n: Int): List { public fun ByteArray.takeLast(n: Int): List { require(n >= 0, { "Requested element count $n is less than zero." }) val size = size() - val realN = if (n > size) size else n + val realN = Math.min(n, size) val list = ArrayList(realN) for (index in size - realN .. size - 1) list.add(this[index]) @@ -1220,7 +1191,7 @@ public fun ByteArray.takeLast(n: Int): List { public fun CharArray.takeLast(n: Int): List { require(n >= 0, { "Requested element count $n is less than zero." }) val size = size() - val realN = if (n > size) size else n + val realN = Math.min(n, size) val list = ArrayList(realN) for (index in size - realN .. size - 1) list.add(this[index]) @@ -1233,7 +1204,7 @@ public fun CharArray.takeLast(n: Int): List { public fun DoubleArray.takeLast(n: Int): List { require(n >= 0, { "Requested element count $n is less than zero." }) val size = size() - val realN = if (n > size) size else n + val realN = Math.min(n, size) val list = ArrayList(realN) for (index in size - realN .. size - 1) list.add(this[index]) @@ -1246,7 +1217,7 @@ public fun DoubleArray.takeLast(n: Int): List { public fun FloatArray.takeLast(n: Int): List { require(n >= 0, { "Requested element count $n is less than zero." }) val size = size() - val realN = if (n > size) size else n + val realN = Math.min(n, size) val list = ArrayList(realN) for (index in size - realN .. size - 1) list.add(this[index]) @@ -1259,7 +1230,7 @@ public fun FloatArray.takeLast(n: Int): List { public fun IntArray.takeLast(n: Int): List { require(n >= 0, { "Requested element count $n is less than zero." }) val size = size() - val realN = if (n > size) size else n + val realN = Math.min(n, size) val list = ArrayList(realN) for (index in size - realN .. size - 1) list.add(this[index]) @@ -1272,7 +1243,7 @@ public fun IntArray.takeLast(n: Int): List { public fun LongArray.takeLast(n: Int): List { require(n >= 0, { "Requested element count $n is less than zero." }) val size = size() - val realN = if (n > size) size else n + val realN = Math.min(n, size) val list = ArrayList(realN) for (index in size - realN .. size - 1) list.add(this[index]) @@ -1285,7 +1256,7 @@ public fun LongArray.takeLast(n: Int): List { public fun ShortArray.takeLast(n: Int): List { require(n >= 0, { "Requested element count $n is less than zero." }) val size = size() - val realN = if (n > size) size else n + val realN = Math.min(n, size) val list = ArrayList(realN) for (index in size - realN .. size - 1) list.add(this[index]) @@ -1298,7 +1269,7 @@ public fun ShortArray.takeLast(n: Int): List { public fun List.takeLast(n: Int): List { require(n >= 0, { "Requested element count $n is less than zero." }) val size = size() - val realN = if (n > size) size else n + val realN = Math.min(n, size) val list = ArrayList(realN) for (index in size - realN .. size - 1) list.add(this[index]) @@ -1309,7 +1280,9 @@ public fun List.takeLast(n: Int): List { * Returns a string containing the last [n] characters from this string, or the entire string if this string is shorter */ public fun String.takeLast(n: Int): String { - return substring(length() - Math.min(n, length()), length()) + require(n >= 0, { "Requested element count $n is less than zero." }) + val length = length() + return substring(length - Math.min(n, length), length) } /** diff --git a/libraries/tools/kotlin-stdlib-gen/src/templates/Filtering.kt b/libraries/tools/kotlin-stdlib-gen/src/templates/Filtering.kt index 5abba8d820d..6845d4428f3 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/templates/Filtering.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/templates/Filtering.kt @@ -12,8 +12,24 @@ fun filtering(): List { body { """ require(n >= 0, { "Requested element count $n is less than zero." }) + val list: ArrayList + if (this is Collection<*>) { + val resultSize = size() - n + if (resultSize <= 0) + return emptyList() + + list = ArrayList(resultSize) + if (this is List) { + for (index in n..size() - 1) { + list.add(this[index]) + } + return list + } + } + else { + list = ArrayList() + } var count = 0 - val list = ArrayList() for (item in this) { if (count++ >= n) list.add(item) } @@ -34,22 +50,7 @@ fun filtering(): List { body(Strings) { "return substring(Math.min(n, length()))" } returns(Strings) { "String" } - body(Collections) { - """ - require(n >= 0, { "Requested element count $n is less than zero." }) - if (n >= size()) - return emptyList() - - var count = 0 - val list = ArrayList(size() - n) - for (item in this) { - if (count++ >= n) list.add(item) - } - return list - """ - } - - body(Lists, ArraysOfObjects, ArraysOfPrimitives) { + body(ArraysOfObjects, ArraysOfPrimitives) { """ require(n >= 0, { "Requested element count $n is less than zero." }) if (n >= size()) @@ -72,7 +73,7 @@ fun filtering(): List { """ require(n >= 0, { "Requested element count $n is less than zero." }) var count = 0 - val list = ArrayList(n) + val list = ArrayList(Math.min(n, collectionSizeOrDefault(n))) for (item in this) { if (count++ == n) break @@ -83,7 +84,12 @@ fun filtering(): List { } doc(Strings) { "Returns a string containing the first [n] characters from this string, or the entire string if this string is shorter"} - body(Strings) { "return substring(0, Math.min(n, length()))" } + body(Strings) { + """ + require(n >= 0, { "Requested element count $n is less than zero." }) + return substring(0, Math.min(n, length())) + """ + } returns(Strings) { "String" } doc(Sequences) { "Returns a sequence containing first *n* elements" } @@ -95,12 +101,11 @@ fun filtering(): List { """ } - include(Collections) - body(Collections, ArraysOfObjects, ArraysOfPrimitives) { + body(ArraysOfObjects, ArraysOfPrimitives) { """ require(n >= 0, "Requested element count $n is less than zero.") var count = 0 - val realN = if (n > size()) size() else n + val realN = Math.min(n, size()) val list = ArrayList(realN) for (item in this) { if (count++ == realN) @@ -119,14 +124,20 @@ fun filtering(): List { returns("List") doc(Strings) { "Returns a string containing the last [n] characters from this string, or the entire string if this string is shorter"} - body(Strings) { "return substring(length() - Math.min(n, length()), length())" } + body(Strings) { + """ + require(n >= 0, { "Requested element count $n is less than zero." }) + val length = length() + return substring(length - Math.min(n, length), length) + """ + } returns(Strings) { "String" } body(Lists, ArraysOfObjects, ArraysOfPrimitives) { """ require(n >= 0, { "Requested element count $n is less than zero." }) val size = size() - val realN = if (n > size) size else n + val realN = Math.min(n, size) val list = ArrayList(realN) for (index in size - realN .. size - 1) list.add(this[index]) @@ -366,7 +377,7 @@ fun filtering(): List { returns("List") body { """ - val list = ArrayList() + val list = ArrayList(indices.collectionSizeOrDefault(10)) for (index in indices) { list.add(get(index)) } @@ -378,7 +389,7 @@ fun filtering(): List { returns(Strings) { "String" } body(Strings) { """ - val result = StringBuilder() + val result = StringBuilder(indices.collectionSizeOrDefault(10)) for (i in indices) { result.append(get(i)) }