Provide overloads both for Strings and CharSequences of filter, filterNot, reversed and partition

This commit is contained in:
Ilya Gorbunov
2015-11-04 06:02:54 +03:00
parent 62d6bcaa6d
commit 05fd2b012a
5 changed files with 106 additions and 75 deletions
+44 -27
View File
@@ -504,31 +504,29 @@ public inline fun String.dropWhile(predicate: (Char) -> Boolean): String {
}
/**
* Returns a string containing only those characters from the original string that match the given [predicate].
* Returns a char sequence containing only those characters from the original char sequence that match the given [predicate].
*/
public inline fun CharSequence.filter(predicate: (Char) -> Boolean): String {
return filterTo(StringBuilder(), predicate).toString()
public inline fun CharSequence.filter(predicate: (Char) -> Boolean): CharSequence {
return filterTo(StringBuilder(), predicate)
}
/**
* Returns a list containing all elements matching the given [predicate].
* Returns a string containing only those characters from the original string that match the given [predicate].
*/
@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN)
public inline fun String.filter(predicate: (Char) -> Boolean): String {
return filterTo(StringBuilder(), predicate).toString()
}
/**
* Returns a string containing only those characters from the original string that do not match the given [predicate].
* Returns a char sequence containing only those characters from the original char sequence that do not match the given [predicate].
*/
public inline fun CharSequence.filterNot(predicate: (Char) -> Boolean): String {
return filterNotTo(StringBuilder(), predicate).toString()
public inline fun CharSequence.filterNot(predicate: (Char) -> Boolean): CharSequence {
return filterNotTo(StringBuilder(), predicate)
}
/**
* Returns a list containing all elements not matching the given [predicate].
* Returns a string containing only those characters from the original string that do not match the given [predicate].
*/
@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN)
public inline fun String.filterNot(predicate: (Char) -> Boolean): String {
return filterNotTo(StringBuilder(), predicate).toString()
}
@@ -574,7 +572,15 @@ public inline fun <C : Appendable> String.filterTo(destination: C, predicate: (C
}
/**
* Returns a string containing characters at indices at the specified [indices].
* Returns a char sequence containing characters of the original char sequence at the specified range of [indices].
*/
public fun CharSequence.slice(indices: IntRange): CharSequence {
if (indices.isEmpty()) return ""
return subSequence(indices)
}
/**
* Returns a string containing characters of the original string at the specified range of [indices].
*/
public fun String.slice(indices: IntRange): String {
if (indices.isEmpty()) return ""
@@ -582,7 +588,20 @@ public fun String.slice(indices: IntRange): String {
}
/**
* Returns a string containing characters at specified [indices].
* Returns a char sequence containing characters of the original char sequence at specified [indices].
*/
public fun CharSequence.slice(indices: Iterable<Int>): CharSequence {
val size = indices.collectionSizeOrDefault(10)
if (size == 0) return ""
val result = StringBuilder(size)
for (i in indices) {
result.append(get(i))
}
return result
}
/**
* Returns a string containing characters of the original string at specified [indices].
*/
public fun String.slice(indices: Iterable<Int>): String {
val size = indices.collectionSizeOrDefault(10)
@@ -675,18 +694,17 @@ public inline fun String.takeWhile(predicate: (Char) -> Boolean): String {
}
/**
* Returns a string with characters in reversed order.
* Returns a char sequence with characters in reversed order.
*/
public fun CharSequence.reversed(): String {
return StringBuilder().append(this).reverse().toString()
public fun CharSequence.reversed(): CharSequence {
return StringBuilder(this).reverse()
}
/**
* Returns a list with elements in reversed order.
* Returns a string with characters in reversed order.
*/
@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN)
public fun String.reversed(): String {
return StringBuilder().append(this).reverse().toString()
return StringBuilder(this).reverse().toString()
}
/**
@@ -1450,11 +1468,11 @@ public inline fun String.sumByDouble(transform: (Char) -> Double): Double {
}
/**
* Splits the original char sequence into pair of strings,
* where *first* string contains characters for which [predicate] yielded `true`,
* while *second* string contains characters for which [predicate] yielded `false`.
* Splits the original char sequence into pair of char sequences,
* where *first* char sequence contains characters for which [predicate] yielded `true`,
* while *second* char sequence contains characters for which [predicate] yielded `false`.
*/
public inline fun CharSequence.partition(predicate: (Char) -> Boolean): Pair<String, String> {
public inline fun CharSequence.partition(predicate: (Char) -> Boolean): Pair<CharSequence, CharSequence> {
val first = StringBuilder()
val second = StringBuilder()
for (element in this) {
@@ -1464,15 +1482,14 @@ public inline fun CharSequence.partition(predicate: (Char) -> Boolean): Pair<Str
second.append(element)
}
}
return Pair(first.toString(), second.toString())
return Pair(first, second)
}
/**
* Splits the original string into pair of lists,
* where *first* list contains elements for which [predicate] yielded `true`,
* while *second* list contains elements for which [predicate] yielded `false`.
* Splits the original string into pair of strings,
* where *first* string contains characters for which [predicate] yielded `true`,
* while *second* string contains characters for which [predicate] yielded `false`.
*/
@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN)
public inline fun String.partition(predicate: (Char) -> Boolean): Pair<String, String> {
val first = StringBuilder()
val second = StringBuilder()
+33 -10
View File
@@ -216,14 +216,20 @@ class StringTest {
assertEquals("aDAB", data.slice(iter).toString())
}
@test fun reverse() = withOneCharSequenceArg { arg1 ->
fun String.reversed(): String = arg1(this).reversed()
@test fun reverse() {
assertEquals("dcba", "abcd".reversed())
assertEquals("4321", "1234".reversed())
assertEquals("", "".reversed())
}
@test fun reverseCharSequence() = withOneCharSequenceArg { arg1 ->
fun String.reversedCs(): CharSequence = arg1(this).reversed()
assertContentEquals("dcba", "abcd".reversedCs())
assertContentEquals("4321", "1234".reversedCs())
assertContentEquals("", "".reversedCs())
}
@test fun indices() = withOneCharSequenceArg { arg1 ->
fun String.indices(): IntRange = arg1(this).indices
@@ -716,14 +722,24 @@ class StringTest {
}
@test fun filter() = withOneCharSequenceArg { arg1 ->
assertEquals("acdca", arg1("abcdcba").filter { !it.equals('b') })
assertEquals("1234", arg1("a1b2c3d4").filter { it.isAsciiDigit() })
@test fun filter() {
assertEquals("acdca", ("abcdcba").filter { !it.equals('b') })
assertEquals("1234", ("a1b2c3d4").filter { it.isAsciiDigit() })
}
@test fun filterNot() = withOneCharSequenceArg { arg1 ->
assertEquals("acdca", arg1("abcdcba").filterNot { it.equals('b') })
assertEquals("abcd", arg1("a1b2c3d4").filterNot { it.isAsciiDigit() })
@test fun filterCharSequence() = withOneCharSequenceArg { arg1 ->
assertContentEquals("acdca", arg1("abcdcba").filter { !it.equals('b') })
assertContentEquals("1234", arg1("a1b2c3d4").filter { it.isAsciiDigit() })
}
@test fun filterNot() {
assertEquals("acdca", ("abcdcba").filterNot { it.equals('b') })
assertEquals("abcd", ("a1b2c3d4").filterNot { it.isAsciiDigit() })
}
@test fun filterNotCharSequence() = withOneCharSequenceArg { arg1 ->
assertContentEquals("acdca", arg1("abcdcba").filterNot { it.equals('b') })
assertContentEquals("abcd", arg1("a1b2c3d4").filterNot { it.isAsciiDigit() })
}
@test fun all() = withOneCharSequenceArg("AbCd") { data ->
@@ -754,12 +770,19 @@ class StringTest {
assertNull(data.filterNot { it.isAsciiLetter() || it.isAsciiDigit() }.firstOrNull())
}
@test fun partition() = withOneCharSequenceArg("a1b2c3") { data ->
@test fun partition() {
val data = "a1b2c3"
val pair = data.partition { it.isAsciiDigit() }
assertEquals("123", pair.first, "pair.first")
assertEquals("abc", pair.second, "pair.second")
}
@test fun partitionCharSequence() = withOneCharSequenceArg("a1b2c3") { data ->
val pair = data.partition { it.isAsciiDigit() }
assertContentEquals("123", pair.first, "pair.first")
assertContentEquals("abc", pair.second, "pair.second")
}
@test fun map() = withOneCharSequenceArg { arg1 ->
assertEquals(listOf('a', 'b', 'c'), arg1("abc").map { it })
@@ -1,6 +1,8 @@
package templates
import templates.Family.*
import templates.DocExtensions.collection
import templates.DocExtensions.element
fun filtering(): List<GenericFunction> {
val templates = arrayListOf<GenericFunction>()
@@ -357,14 +359,9 @@ fun filtering(): List<GenericFunction> {
"""
}
deprecate(Strings) { forBinaryCompatibility }
doc(CharSequences) { "Returns a string containing only those characters from the original string that match the given [predicate]." }
returns(CharSequences, Strings) { "String" }
body(CharSequences, Strings) {
"""
return filterTo(StringBuilder(), predicate).toString()
"""
}
doc(CharSequences, Strings) { f -> "Returns a ${f.collection} containing only those characters from the original ${f.collection} that match the given [predicate]." }
returns(CharSequences, Strings) { "SELF" }
body(CharSequences, Strings) { f -> """return filterTo(StringBuilder(), predicate)${toResult(f)}""" }
inline(false, Sequences)
doc(Sequences) { "Returns a sequence containing all elements matching the given [predicate]." }
@@ -414,14 +411,9 @@ fun filtering(): List<GenericFunction> {
"""
}
deprecate(Strings) { forBinaryCompatibility }
doc(CharSequences) { "Returns a string containing only those characters from the original string that do not match the given [predicate]." }
returns(CharSequences, Strings) { "String" }
body(CharSequences, Strings) {
"""
return filterNotTo(StringBuilder(), predicate).toString()
"""
}
doc(CharSequences, Strings) { f -> "Returns a ${f.collection} containing only those characters from the original ${f.collection} that do not match the given [predicate]." }
returns(CharSequences, Strings) { "SELF" }
body(CharSequences, Strings) { f -> """return filterNotTo(StringBuilder(), predicate)${toResult(f)}""" }
inline(false, Sequences)
doc(Sequences) { "Returns a sequence containing all elements not matching the given [predicate]." }
@@ -509,9 +501,9 @@ fun filtering(): List<GenericFunction> {
"""
}
doc(Strings) { "Returns a string containing characters at specified [indices]." }
returns(Strings) { "String" }
body(Strings) {
doc(CharSequences, Strings) { f -> "Returns a ${f.collection} containing ${f.element}s of the original ${f.collection} at specified [indices]." }
returns(CharSequences, Strings) { "SELF" }
body(CharSequences, Strings) { f ->
"""
val size = indices.collectionSizeOrDefault(10)
if (size == 0) return ""
@@ -519,7 +511,7 @@ fun filtering(): List<GenericFunction> {
for (i in indices) {
result.append(get(i))
}
return result.toString()
return result${toResult(f)}
"""
}
}
@@ -541,12 +533,12 @@ fun filtering(): List<GenericFunction> {
"""
}
doc(Strings) { "Returns a string containing characters at indices at the specified [indices]." }
returns(Strings) { "String" }
body(Strings) {
doc(CharSequences, Strings) { f -> "Returns a ${f.collection} containing ${f.element}s of the original ${f.collection} at the specified range of [indices]." }
returns(CharSequences, Strings) { "SELF" }
body(CharSequences, Strings) { f ->
"""
if (indices.isEmpty()) return ""
return substring(indices)
return ${ mapOf(Strings to "substring", CharSequences to "subSequence")[f]}(indices)
"""
}
}
@@ -420,16 +420,16 @@ fun generators(): List<GenericFunction> {
"""
}
deprecate(Strings) { forBinaryCompatibility }
doc(CharSequences) {
doc(CharSequences, Strings) { f ->
"""
Splits the original char sequence into pair of strings,
where *first* string contains characters for which [predicate] yielded `true`,
while *second* string contains characters for which [predicate] yielded `false`.
Splits the original ${f.collection} into pair of ${f.collection}s,
where *first* ${f.collection} contains characters for which [predicate] yielded `true`,
while *second* ${f.collection} contains characters for which [predicate] yielded `false`.
"""
}
returns(CharSequences, Strings) { "Pair<String, String>" }
body(CharSequences, Strings) {
returns(CharSequences, Strings) { "Pair<SELF, SELF>" }
body(CharSequences, Strings) { f ->
val toString = if (f == Strings) ".toString()" else ""
"""
val first = StringBuilder()
val second = StringBuilder()
@@ -440,7 +440,7 @@ fun generators(): List<GenericFunction> {
second.append(element)
}
}
return Pair(first.toString(), second.toString())
return Pair(first$toString, second$toString)
"""
}
}
@@ -1,6 +1,7 @@
package templates
import templates.Family.*
import templates.DocExtensions.collection
fun ordering(): List<GenericFunction> {
val templates = arrayListOf<GenericFunction>()
@@ -39,13 +40,11 @@ fun ordering(): List<GenericFunction> {
"""
}
deprecate(Strings) { forBinaryCompatibility }
doc(CharSequences) { "Returns a string with characters in reversed order." }
returns(CharSequences, Strings) { "String" }
body(CharSequences, Strings) {
// TODO: Replace with StringBuilder(this) when JS can handle it
doc(CharSequences, Strings) { f -> "Returns a ${f.collection} with characters in reversed order." }
returns(CharSequences, Strings) { "SELF" }
body(CharSequences, Strings) { f ->
"""
return StringBuilder().append(this).reverse().toString()
return StringBuilder(this).reverse()${ if (f == Strings) ".toString()" else "" }
"""
}