Support String in generators, and migrate generated functions.

This commit is contained in:
Ilya Ryzhenkov
2014-04-08 15:40:53 +04:00
committed by Andrey Breslav
parent d9d5631a16
commit cbc0e6404e
22 changed files with 971 additions and 454 deletions
@@ -115,6 +115,15 @@ public inline fun <T> Stream<T>.all(predicate: (T) -> Boolean) : Boolean {
}
/**
* Returns *true* if all elements match the given *predicate*
*/
public inline fun String.all(predicate: (Char) -> Boolean) : Boolean {
for (element in this) if (!predicate(element)) return false
return true
}
/**
* Returns *true* if collection has at least one element
*/
@@ -223,6 +232,15 @@ public fun <T> Stream<T>.any() : Boolean {
}
/**
* Returns *true* if collection has at least one element
*/
public fun String.any() : Boolean {
for (element in this) return true
return false
}
/**
* Returns *true* if any element matches the given *predicate*
*/
@@ -331,6 +349,15 @@ public inline fun <T> Stream<T>.any(predicate: (T) -> Boolean) : Boolean {
}
/**
* Returns *true* if any element matches the given *predicate*
*/
public inline fun String.any(predicate: (Char) -> Boolean) : Boolean {
for (element in this) if (predicate(element)) return true
return false
}
/**
* Returns the number of elements
*/
@@ -428,6 +455,13 @@ public fun <T> Stream<T>.count() : Int {
}
/**
* Returns the number of elements
*/
public fun String.count() : Int {
return size
}
/**
* Returns the number of elements matching the given *predicate*
*/
@@ -548,6 +582,16 @@ public inline fun <T> Stream<T>.count(predicate: (T) -> Boolean) : Int {
}
/**
* Returns the number of elements matching the given *predicate*
*/
public inline fun String.count(predicate: (Char) -> Boolean) : Int {
var count = 0
for (element in this) if (predicate(element)) count++
return count
}
/**
* Accumulates value starting with *initial* value and applying *operation* from left to right to current accumulator value and each element
*/
@@ -658,6 +702,16 @@ public inline fun <T, R> Stream<T>.fold(initial: R, operation: (R, T) -> R) : R
}
/**
* Accumulates value starting with *initial* value and applying *operation* from left to right to current accumulator value and each element
*/
public inline fun <R> String.fold(initial: R, operation: (R, Char) -> R) : R {
var accumulator = initial
for (element in this) accumulator = operation(accumulator, element)
return accumulator
}
/**
* Accumulates value starting with *initial* value and applying *operation* from right to left to each element and current accumulator value
*/
@@ -788,6 +842,19 @@ public inline fun <T, R> List<T>.foldRight(initial: R, operation: (T, R) -> R) :
}
/**
* Accumulates value starting with *initial* value and applying *operation* from right to left to each element and current accumulator value
*/
public inline fun <R> String.foldRight(initial: R, operation: (Char, R) -> R) : R {
var index = size - 1
var accumulator = initial
while (index >= 0) {
accumulator = operation(get(index--), accumulator)
}
return accumulator
}
/**
* Performs the given *operation* on each element
*/
@@ -884,6 +951,14 @@ public inline fun <T> Stream<T>.forEach(operation: (T) -> Unit) : Unit {
}
/**
* Performs the given *operation* on each element
*/
public inline fun String.forEach(operation: (Char) -> Unit) : Unit {
for (element in this) operation(element)
}
/**
* Returns the largest element or null if there are no elements
*/
@@ -1036,6 +1111,22 @@ public fun <T: Comparable<T>> Stream<T>.max() : T? {
}
/**
* Returns the largest element or null if there are no elements
*/
public fun String.max() : Char? {
val iterator = iterator()
if (!iterator.hasNext()) return null
var max = iterator.next()
while (iterator.hasNext()) {
val e = iterator.next()
if (max < e) max = e
}
return max
}
/**
* Returns the first element yielding the largest value of the given function or null if there are no elements
*/
@@ -1258,6 +1349,27 @@ public inline fun <R: Comparable<R>, T: Any> Stream<T>.maxBy(f: (T) -> R) : T? {
}
/**
* Returns the first element yielding the largest value of the given function or null if there are no elements
*/
public inline fun <R: Comparable<R>> String.maxBy(f: (Char) -> R) : Char? {
val iterator = iterator()
if (!iterator.hasNext()) return null
var maxElem = iterator.next()
var maxValue = f(maxElem)
while (iterator.hasNext()) {
val e = iterator.next()
val v = f(e)
if (maxValue < v) {
maxElem = e
maxValue = v
}
}
return maxElem
}
/**
* Returns the first element yielding the largest value of the given function or null if there are no elements
*/
@@ -1423,6 +1535,22 @@ public fun <T: Comparable<T>> Stream<T>.min() : T? {
}
/**
* Returns the smallest element or null if there are no elements
*/
public fun String.min() : Char? {
val iterator = iterator()
if (!iterator.hasNext()) return null
var min = iterator.next()
while (iterator.hasNext()) {
val e = iterator.next()
if (min > e) min = e
}
return min
}
/**
* Returns the first element yielding the smallest value of the given function or null if there are no elements
*/
@@ -1645,6 +1773,27 @@ public inline fun <R: Comparable<R>, T: Any> Stream<T>.minBy(f: (T) -> R) : T? {
}
/**
* Returns the first element yielding the smallest value of the given function or null if there are no elements
*/
public inline fun <R: Comparable<R>> String.minBy(f: (Char) -> R) : Char? {
val iterator = iterator()
if (!iterator.hasNext()) return null
var minElem = iterator.next()
var minValue = f(minElem)
while (iterator.hasNext()) {
val e = iterator.next()
val v = f(e)
if (minValue > v) {
minElem = e
minValue = v
}
}
return minElem
}
/**
* Returns the first element yielding the smallest value of the given function or null if there are no elements
*/
@@ -1774,6 +1923,15 @@ public fun <T> Stream<T>.none() : Boolean {
}
/**
* Returns *true* if collection has no elements
*/
public fun String.none() : Boolean {
for (element in this) return false
return true
}
/**
* Returns *true* if no elements match the given *predicate*
*/
@@ -1882,6 +2040,15 @@ public inline fun <T> Stream<T>.none(predicate: (T) -> Boolean) : Boolean {
}
/**
* Returns *true* if no elements match the given *predicate*
*/
public inline fun String.none(predicate: (Char) -> Boolean) : Boolean {
for (element in this) if (predicate(element)) return false
return true
}
/**
* Accumulates value starting with the first element and applying *operation* from left to right to current accumulator value and each element
*/
@@ -2047,6 +2214,21 @@ public inline fun <T> Stream<T>.reduce(operation: (T, T) -> T) : T {
}
/**
* Accumulates value starting with the first element and applying *operation* from left to right to current accumulator value and each element
*/
public inline fun String.reduce(operation: (Char, Char) -> Char) : Char {
val iterator = this.iterator()
if (!iterator.hasNext()) throw UnsupportedOperationException("Empty iterable can't be reduced")
var accumulator = iterator.next()
while (iterator.hasNext()) {
accumulator = operation(accumulator, iterator.next())
}
return accumulator
}
/**
* Accumulates value starting with last element and applying *operation* from right to left to each element and current accumulator value
*/
@@ -2207,3 +2389,19 @@ public inline fun <T> List<T>.reduceRight(operation: (T, T) -> T) : T {
}
/**
* Accumulates value starting with last element and applying *operation* from right to left to each element and current accumulator value
*/
public inline fun String.reduceRight(operation: (Char, Char) -> Char) : Char {
var index = size - 1
if (index < 0) throw UnsupportedOperationException("Empty iterable can't be reduced")
var accumulator = get(index--)
while (index >= 0) {
accumulator = operation(get(index--), accumulator)
}
return accumulator
}
@@ -211,6 +211,14 @@ public fun <T> Stream<T>.elementAt(index : Int) : T {
}
/**
* Returns element at given *index*
*/
public fun String.elementAt(index : Int) : Char {
return get(index)
}
/**
* Returns first element
*/
@@ -351,6 +359,16 @@ public fun <T> Stream<T>.first(): T {
}
}
/**
* Returns first element
*/
public fun String.first() : Char {
if (size == 0)
throw IllegalArgumentException("Collection is empty")
return this[0]
}
/**
* Returns first element matching the given *predicate*
*/
@@ -450,6 +468,15 @@ public inline fun <T> Stream<T>.first(predicate: (T) -> Boolean) : T {
}
/**
* Returns first element matching the given *predicate*
*/
public inline fun String.first(predicate: (Char) -> Boolean) : Char {
for (element in this) if (predicate(element)) return element
throw IllegalArgumentException("No element matching predicate was found")
}
/**
* Returns first elementm, or null if collection is empty
*/
@@ -570,6 +597,14 @@ public fun <T> Stream<T>.firstOrNull(): T? {
}
}
/**
* Returns first elementm, or null if collection is empty
*/
public fun String.firstOrNull() : Char? {
return if (size > 0) this[0] else null
}
/**
* Returns first element matching the given *predicate*, or *null* if element was not found
*/
@@ -669,6 +704,15 @@ public inline fun <T> Stream<T>.firstOrNull(predicate: (T) -> Boolean) : T? {
}
/**
* Returns first element matching the given *predicate*, or *null* if element was not found
*/
public inline fun String.firstOrNull(predicate: (Char) -> Boolean) : Char? {
for (element in this) if (predicate(element)) return element
return null
}
/**
* Returns first index of *element*, or -1 if the collection does not contain element
*/
@@ -966,6 +1010,16 @@ public fun <T> Stream<T>.last() : T {
}
/**
* Returns last element
*/
public fun String.last() : Char {
if (size == 0)
throw IllegalArgumentException("Collection is empty")
return this[size - 1]
}
/**
* Returns last element matching the given *predicate*
*/
@@ -1464,6 +1518,14 @@ public fun <T> Stream<T>.lastOrNull() : T? {
}
/**
* Returns last element, or null if collection is empty
*/
public fun String.lastOrNull() : Char? {
return if (size > 0) this[size - 1] else null
}
/**
* Returns last element matching the given *predicate*, or null if element was not found
*/
@@ -1770,6 +1832,16 @@ public fun <T> Stream<T>.single() : T {
}
/**
* Returns single element, or throws exception if there is no or more than one element
*/
public fun String.single() : Char {
if (size != 1)
throw IllegalArgumentException("Collection has $size elements")
return this[0]
}
/**
* Returns single element matching the given *predicate*, or throws exception if there is no or more than one element
*/
@@ -2144,6 +2216,18 @@ public fun <T> Stream<T>.singleOrNull() : T? {
}
/**
* Returns single element, or null if collection is empty, or throws exception if there is more than one element
*/
public fun String.singleOrNull() : Char? {
if (size == 0)
return null
if (size != 1)
throw IllegalArgumentException("Collection has $size elements")
return this[0]
}
/**
* Returns single element matching the given *predicate*, or null if element was not found or more than one elements were found
*/
@@ -189,6 +189,13 @@ public fun <T> Stream<T>.drop(n: Int) : Stream<T> {
}
/**
* Returns a list containing all elements except first *n* elements
*/
public fun String.drop(n: Int) : String {
return substring(Math.min(n, size))
}
/**
* Returns a list containing all elements except first elements that satisfy the given *predicate*
*/
@@ -376,6 +383,18 @@ public fun <T> Stream<T>.dropWhile(predicate: (T)->Boolean) : Stream<T> {
}
/**
* Returns a list containing all elements except first elements that satisfy the given *predicate*
*/
public inline fun String.dropWhile(predicate: (Char) -> Boolean): String {
for (index in 0..length)
if (!predicate(get(index))) {
return substring(index)
}
return ""
}
/**
* Returns a list containing all elements matching the given *predicate*
*/
@@ -472,6 +491,14 @@ public fun <T> Stream<T>.filter(predicate: (T)->Boolean) : Stream<T> {
}
/**
* Returns a list containing all elements matching the given *predicate*
*/
public inline fun String.filter(predicate: (Char)->Boolean) : String {
return filterTo(StringBuilder(), predicate).toString()
}
/**
* Returns a list containing all elements not matching the given *predicate*
*/
@@ -568,6 +595,14 @@ public fun <T> Stream<T>.filterNot(predicate: (T)->Boolean) : Stream<T> {
}
/**
* Returns a list containing all elements not matching the given *predicate*
*/
public inline fun String.filterNot(predicate: (Char)->Boolean) : String {
return filterNotTo(StringBuilder(), predicate).toString()
}
/**
* Returns a list containing all elements that are not null
*/
@@ -727,6 +762,15 @@ public inline fun <T, C: MutableCollection<in T>> Stream<T>.filterNotTo(collecti
}
/**
* Appends all characters not matching the given *predicate* to the given *collection*
*/
public inline fun <C: Appendable> String.filterNotTo(collection: C, predicate: (Char) -> Boolean) : C {
for (element in this) if (!predicate(element)) collection.append(element)
return collection
}
/**
* Appends all elements matching the given *predicate* into the given *collection*
*/
@@ -835,6 +879,17 @@ public inline fun <T, C: MutableCollection<in T>> Stream<T>.filterTo(collection:
}
/**
* Appends all characters matching the given *predicate* to the given *collection*
*/
public inline fun <C : Appendable> String.filterTo(destination: C, predicate: (Char) -> Boolean): C {
for (index in 0..length - 1) {
val element = get(index)
if (predicate(element)) destination.append(element)
}
return destination
}
/**
* Returns a list containing elements at specified positions
*/
@@ -955,6 +1010,18 @@ public fun <T> List<T>.slice(indices: Iterable<Int>) : List<T> {
}
/**
* Returns a list containing elements at specified positions
*/
public fun String.slice(indices: Iterable<Int>) : String {
val result = StringBuilder()
for (i in indices) {
result.append(get(i))
}
return result.toString()
}
/**
* Returns a list containing first *n* elements
*/
@@ -1139,6 +1206,13 @@ public fun <T> Stream<T>.take(n: Int) : Stream<T> {
}
/**
* Returns a list containing first *n* elements
*/
public fun String.take(n: Int) : String {
return substring(0, Math.min(n, size))
}
/**
* Returns a list containing first elements satisfying the given *predicate*
*/
@@ -1287,3 +1361,15 @@ public fun <T> Stream<T>.takeWhile(predicate: (T)->Boolean) : Stream<T> {
}
/**
* Returns a list containing first elements satisfying the given *predicate*
*/
public inline fun String.takeWhile(predicate: (Char) -> Boolean): String {
for (index in 0..length)
if (!predicate(get(index))) {
return substring(0, index)
}
return ""
}
+81 -20
View File
@@ -216,6 +216,25 @@ public inline fun <T> Stream<T>.partition(predicate: (T) -> Boolean) : Pair<List
}
/**
* Splits original collection into pair of collections,
* where *first* collection contains elements for which predicate yielded *true*,
* while *second* collection contains elements for which predicate yielded *false*
*/
public inline fun String.partition(predicate: (Char) -> Boolean) : Pair<String, String> {
val first = StringBuilder()
val second = StringBuilder()
for (element in this) {
if (predicate(element)) {
first.append(element)
} else {
second.append(element)
}
}
return Pair(first.toString(), second.toString())
}
/**
* Returns a list containing all elements of original collection and then all elements of the given *collection*
*/
@@ -683,9 +702,37 @@ public fun <T, R> Iterable<T>.zip(array: Array<R>) : List<Pair<T,R>> {
/**
* Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection.
*/
public fun <T, R> Array<out T>.zip(collection: Iterable<R>) : List<Pair<T,R>> {
public fun <R> String.zip(array: Array<R>) : List<Pair<Char,R>> {
val first = iterator()
val second = collection.iterator()
val second = array.iterator()
val list = ArrayList<Pair<Char,R>>()
while (first.hasNext() && second.hasNext()) {
list.add(first.next() to second.next())
}
return list
}
/**
* Returns a list of pairs built from characters of both strings with same indexes. List has length of shortest collection.
*/
public fun String.zip(other : String) : List<Pair<Char,Char>> {
val first = iterator()
val second = other.iterator()
val list = ArrayList<Pair<Char,Char>>()
while (first.hasNext() && second.hasNext()) {
list.add(first.next() to second.next())
}
return list
}
/**
* Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection.
*/
public fun <T, R> Array<out T>.zip(other: Iterable<R>) : List<Pair<T,R>> {
val first = iterator()
val second = other.iterator()
val list = ArrayList<Pair<T,R>>()
while (first.hasNext() && second.hasNext()) {
list.add(first.next() to second.next())
@@ -697,9 +744,9 @@ public fun <T, R> Array<out T>.zip(collection: Iterable<R>) : List<Pair<T,R>> {
/**
* Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection.
*/
public fun <R> BooleanArray.zip(collection: Iterable<R>) : List<Pair<Boolean,R>> {
public fun <R> BooleanArray.zip(other: Iterable<R>) : List<Pair<Boolean,R>> {
val first = iterator()
val second = collection.iterator()
val second = other.iterator()
val list = ArrayList<Pair<Boolean,R>>()
while (first.hasNext() && second.hasNext()) {
list.add(first.next() to second.next())
@@ -711,9 +758,9 @@ public fun <R> BooleanArray.zip(collection: Iterable<R>) : List<Pair<Boolean,R>>
/**
* Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection.
*/
public fun <R> ByteArray.zip(collection: Iterable<R>) : List<Pair<Byte,R>> {
public fun <R> ByteArray.zip(other: Iterable<R>) : List<Pair<Byte,R>> {
val first = iterator()
val second = collection.iterator()
val second = other.iterator()
val list = ArrayList<Pair<Byte,R>>()
while (first.hasNext() && second.hasNext()) {
list.add(first.next() to second.next())
@@ -725,9 +772,9 @@ public fun <R> ByteArray.zip(collection: Iterable<R>) : List<Pair<Byte,R>> {
/**
* Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection.
*/
public fun <R> CharArray.zip(collection: Iterable<R>) : List<Pair<Char,R>> {
public fun <R> CharArray.zip(other: Iterable<R>) : List<Pair<Char,R>> {
val first = iterator()
val second = collection.iterator()
val second = other.iterator()
val list = ArrayList<Pair<Char,R>>()
while (first.hasNext() && second.hasNext()) {
list.add(first.next() to second.next())
@@ -739,9 +786,9 @@ public fun <R> CharArray.zip(collection: Iterable<R>) : List<Pair<Char,R>> {
/**
* Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection.
*/
public fun <R> DoubleArray.zip(collection: Iterable<R>) : List<Pair<Double,R>> {
public fun <R> DoubleArray.zip(other: Iterable<R>) : List<Pair<Double,R>> {
val first = iterator()
val second = collection.iterator()
val second = other.iterator()
val list = ArrayList<Pair<Double,R>>()
while (first.hasNext() && second.hasNext()) {
list.add(first.next() to second.next())
@@ -753,9 +800,9 @@ public fun <R> DoubleArray.zip(collection: Iterable<R>) : List<Pair<Double,R>> {
/**
* Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection.
*/
public fun <R> FloatArray.zip(collection: Iterable<R>) : List<Pair<Float,R>> {
public fun <R> FloatArray.zip(other: Iterable<R>) : List<Pair<Float,R>> {
val first = iterator()
val second = collection.iterator()
val second = other.iterator()
val list = ArrayList<Pair<Float,R>>()
while (first.hasNext() && second.hasNext()) {
list.add(first.next() to second.next())
@@ -767,9 +814,9 @@ public fun <R> FloatArray.zip(collection: Iterable<R>) : List<Pair<Float,R>> {
/**
* Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection.
*/
public fun <R> IntArray.zip(collection: Iterable<R>) : List<Pair<Int,R>> {
public fun <R> IntArray.zip(other: Iterable<R>) : List<Pair<Int,R>> {
val first = iterator()
val second = collection.iterator()
val second = other.iterator()
val list = ArrayList<Pair<Int,R>>()
while (first.hasNext() && second.hasNext()) {
list.add(first.next() to second.next())
@@ -781,9 +828,9 @@ public fun <R> IntArray.zip(collection: Iterable<R>) : List<Pair<Int,R>> {
/**
* Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection.
*/
public fun <R> LongArray.zip(collection: Iterable<R>) : List<Pair<Long,R>> {
public fun <R> LongArray.zip(other: Iterable<R>) : List<Pair<Long,R>> {
val first = iterator()
val second = collection.iterator()
val second = other.iterator()
val list = ArrayList<Pair<Long,R>>()
while (first.hasNext() && second.hasNext()) {
list.add(first.next() to second.next())
@@ -795,9 +842,9 @@ public fun <R> LongArray.zip(collection: Iterable<R>) : List<Pair<Long,R>> {
/**
* Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection.
*/
public fun <R> ShortArray.zip(collection: Iterable<R>) : List<Pair<Short,R>> {
public fun <R> ShortArray.zip(other: Iterable<R>) : List<Pair<Short,R>> {
val first = iterator()
val second = collection.iterator()
val second = other.iterator()
val list = ArrayList<Pair<Short,R>>()
while (first.hasNext() && second.hasNext()) {
list.add(first.next() to second.next())
@@ -809,9 +856,9 @@ public fun <R> ShortArray.zip(collection: Iterable<R>) : List<Pair<Short,R>> {
/**
* Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection.
*/
public fun <T, R> Iterable<T>.zip(collection: Iterable<R>) : List<Pair<T,R>> {
public fun <T, R> Iterable<T>.zip(other: Iterable<R>) : List<Pair<T,R>> {
val first = iterator()
val second = collection.iterator()
val second = other.iterator()
val list = ArrayList<Pair<T,R>>()
while (first.hasNext() && second.hasNext()) {
list.add(first.next() to second.next())
@@ -820,6 +867,20 @@ public fun <T, R> Iterable<T>.zip(collection: Iterable<R>) : List<Pair<T,R>> {
}
/**
* Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection.
*/
public fun <R> String.zip(other: Iterable<R>) : List<Pair<Char,R>> {
val first = iterator()
val second = other.iterator()
val list = ArrayList<Pair<Char,R>>()
while (first.hasNext() && second.hasNext()) {
list.add(first.next() to second.next())
}
return list
}
/**
* Returns a stream of pairs built from elements of both collections with same indexes. List has length of shortest collection.
*/
+68 -2
View File
@@ -84,6 +84,13 @@ public inline fun <K, V, R> Map<K,V>.flatMap(transform: (Map.Entry<K,V>)-> Itera
return flatMapTo(ArrayList<R>(), transform)
}
/**
* Returns a single list of all elements yielded from results of *transform* function being invoked on each element of original collection
*/
public inline fun <R> String.flatMap(transform: (Char)-> Iterable<R>) : List<R> {
return flatMapTo(ArrayList<R>(), transform)
}
/**
* Returns a single stream of all elements streamed from results of *transform* function being invoked on each element of original stream
*/
@@ -223,6 +230,18 @@ public inline fun <K, V, R, C: MutableCollection<in R>> Map<K,V>.flatMapTo(colle
}
/**
* Appends all elements yielded from results of *transform* function being invoked on each element of original collection, to the given *collection*
*/
public inline fun <R, C: MutableCollection<in R>> String.flatMapTo(collection: C, transform: (Char) -> Iterable<R>) : C {
for (element in this) {
val list = transform(element)
collection.addAll(list)
}
return collection
}
/**
* Appends all elements yielded from results of *transform* function being invoked on each element of original stream, to the given *collection*
*/
@@ -319,6 +338,13 @@ public inline fun <T, K> Stream<T>.groupBy(toKey: (T) -> K) : Map<K, List<T>> {
return groupByTo(HashMap<K, MutableList<T>>(), toKey)
}
/**
* Returns a map of the elements in original collection grouped by the result of given *toKey* function
*/
public inline fun <K> String.groupBy(toKey: (Char) -> K) : Map<K, List<Char>> {
return groupByTo(HashMap<K, MutableList<Char>>(), toKey)
}
/**
* Appends elements from original collection grouped by the result of given *toKey* function to the given *map*
*/
@@ -475,6 +501,19 @@ public inline fun <T, K> Stream<T>.groupByTo(map: MutableMap<K, MutableList<T>>,
}
/**
* Appends elements from original collection grouped by the result of given *toKey* function to the given *map*
*/
public inline fun <K> String.groupByTo(map: MutableMap<K, MutableList<Char>>, toKey: (Char) -> K) : Map<K, MutableList<Char>> {
for (element in this) {
val key = toKey(element)
val list = map.getOrPut(key) { ArrayList<Char>() }
list.add(element)
}
return map
}
/**
* Returns a list containing the results of applying the given *transform* function to each element of the original collection
*/
@@ -559,10 +598,17 @@ public fun <T, R> Stream<T>.map(transform : (T) -> R) : Stream<R> {
return TransformingStream(this, transform)
}
/**
* Returns a list containing the results of applying the given *transform* function to each element of the original collection
*/
public inline fun <R> String.map(transform : (Char) -> R) : List<R> {
return mapTo(ArrayList<R>(), transform)
}
/**
* Returns a list containing the results of applying the given *transform* function to each non-null element of the original collection
*/
public fun <T: Any, R> Array<T?>.mapNotNull(transform : (T) -> R) : List<R> {
public inline fun <T: Any, R> Array<T?>.mapNotNull(transform : (T) -> R) : List<R> {
return mapNotNullTo(ArrayList<R>(), transform)
}
@@ -570,7 +616,7 @@ public fun <T: Any, R> Array<T?>.mapNotNull(transform : (T) -> R) : List<R> {
/**
* Returns a list containing the results of applying the given *transform* function to each non-null element of the original collection
*/
public fun <T: Any, R> Iterable<T?>.mapNotNull(transform : (T) -> R) : List<R> {
public inline fun <T: Any, R> Iterable<T?>.mapNotNull(transform : (T) -> R) : List<R> {
return mapNotNullTo(ArrayList<R>(), transform)
}
@@ -757,6 +803,17 @@ public inline fun <T, R, C: MutableCollection<in R>> Stream<T>.mapTo(collection:
}
/**
* Appends transformed elements of original collection using the given *transform* function
* to the given *collection*
*/
public inline fun <R, C: MutableCollection<in R>> String.mapTo(collection: C, transform : (Char) -> R) : C {
for (item in this)
collection.add(transform(item))
return collection
}
/**
* Returns a list containing pairs of each element of the original collection and their index
*/
@@ -856,3 +913,12 @@ 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
*/
public fun String.withIndices() : List<Pair<Int, Char>> {
var index = 0
return mapTo(ArrayList<Pair<Int, Char>>(), { index++ to it })
}
@@ -107,6 +107,14 @@ public fun <T> Iterable<T>.reverse() : List<T> {
}
/**
* Returns a string with characters in reversed order
*/
public fun String.reverse() : String {
return StringBuilder().append(this).reverse().toString()
}
/**
* Returns a sorted list of all elements
*/
@@ -111,6 +111,13 @@ public fun <T> Stream<T>.toArrayList() : ArrayList<T> {
return toCollection(ArrayList<T>())
}
/**
* Returns an ArrayList of all elements
*/
public fun String.toArrayList() : ArrayList<Char> {
return toCollection(ArrayList<Char>())
}
/**
* Appends all elements to the given *collection*
*/
@@ -232,6 +239,17 @@ public fun <T, C : MutableCollection<in T>> Stream<T>.toCollection(collection :
}
/**
* Appends all elements to the given *collection*
*/
public fun <C : MutableCollection<in Char>> String.toCollection(collection : C) : C {
for (item in this) {
collection.add(item)
}
return collection
}
/**
* Returns a HashSet of all elements
*/
@@ -309,6 +327,13 @@ public fun <T> Stream<T>.toHashSet() : HashSet<T> {
return toCollection(HashSet<T>())
}
/**
* Returns a HashSet of all elements
*/
public fun String.toHashSet() : HashSet<Char> {
return toCollection(HashSet<Char>())
}
/**
* Returns a LinkedList containing all elements
*/
@@ -386,6 +411,13 @@ public fun <T> Stream<T>.toLinkedList() : LinkedList<T> {
return toCollection(LinkedList<T>())
}
/**
* Returns a LinkedList containing all elements
*/
public fun String.toLinkedList() : LinkedList<Char> {
return toCollection(LinkedList<Char>())
}
/**
* Returns a List containing all elements
*/
@@ -487,6 +519,13 @@ public fun <T> Stream<T>.toList() : List<T> {
return toCollection(ArrayList<T>())
}
/**
* Returns a List containing all elements
*/
public fun String.toList() : List<Char> {
return toCollection(ArrayList<Char>())
}
/**
* Returns a Set of all elements
*/
@@ -564,6 +603,13 @@ public fun <T> Stream<T>.toSet() : Set<T> {
return toCollection(LinkedHashSet<T>())
}
/**
* Returns a Set of all elements
*/
public fun String.toSet() : Set<Char> {
return toCollection(LinkedHashSet<Char>())
}
/**
* Returns a sorted list of all elements
*/
@@ -641,6 +687,13 @@ public fun <T: Comparable<T>> Stream<T>.toSortedList() : List<T> {
return toArrayList().sort()
}
/**
* Returns a sorted list of all elements
*/
public fun String.toSortedList() : List<Char> {
return toArrayList().sort()
}
/**
* Returns a SortedSet of all elements
*/
@@ -718,3 +771,10 @@ public fun <T> Stream<T>.toSortedSet() : SortedSet<T> {
return toCollection(TreeSet<T>())
}
/**
* Returns a SortedSet of all elements
*/
public fun String.toSortedSet() : SortedSet<Char> {
return toCollection(TreeSet<Char>())
}
@@ -357,6 +357,14 @@ public fun <T, R: T> Stream<T>.filterIsInstance(klass: Class<R>) : Stream<T> {
}
/**
* Returns a list containing all elements that are instances of specified class
*/
public fun <R: Char> String.filterIsInstance(klass: Class<R>) : List<R> {
return filterIsInstanceTo(ArrayList<R>(), klass)
}
/**
* Appends all elements that are instances of specified class into the given *collection*
*/
@@ -384,6 +392,15 @@ public fun <T, C: MutableCollection<in R>, R: T> Stream<T>.filterIsInstanceTo(co
}
/**
* Appends all elements that are instances of specified class into the given *collection*
*/
public fun <C: MutableCollection<in R>, R: Char> String.filterIsInstanceTo(collection: C, klass: Class<R>) : C {
for (element in this) if (klass.isInstance(element)) collection.add(element as R)
return collection
}
/**
* Sorts array or range in array inplace
*/
@@ -95,3 +95,11 @@ public fun <T> Stream<T>.stream() : Stream<T> {
}
/**
* Returns a stream from the given collection
*/
public fun String.stream() : Stream<Char> {
return object : Stream<Char> { override fun iterator() : Iterator<Char> { return this@stream.iterator() } }
}
@@ -227,6 +227,26 @@ public fun <T> Stream<T>.appendString(buffer: Appendable, separator: String = ",
}
/**
* Appends the string from all the elements separated using the *separator* and using the given *prefix* and *postfix* if supplied
* If a collection could be huge you can specify a non-negative value of *limit* which will only show a subset of the collection then it will
* a special *truncated* separator (which defaults to "..."
*/
public fun String.appendString(buffer: Appendable, separator: String = ", ", prefix: String ="", postfix: String = "", limit: Int = -1, truncated: String = "...") : Unit {
buffer.append(prefix)
var count = 0
for (element in this) {
if (++count > 1) buffer.append(separator)
if (limit < 0 || count <= limit) {
val text = if (element == null) "null" else element.toString()
buffer.append(text)
} else break
}
if (limit >= 0 && count > limit) buffer.append(truncated)
buffer.append(postfix)
}
/**
* Creates a string from all the elements separated using the *separator* and using the given *prefix* and *postfix* if supplied.
* If a collection could be huge you can specify a non-negative value of *limit* which will only show a subset of the collection then it will
@@ -359,3 +379,15 @@ public fun <T> Stream<T>.makeString(separator: String = ", ", prefix: String = "
}
/**
* Creates a string from all the elements separated using the *separator* and using the given *prefix* and *postfix* if supplied.
* If a collection could be huge you can specify a non-negative value of *limit* which will only show a subset of the collection then it will
* a special *truncated* separator (which defaults to "..."
*/
public fun String.makeString(separator: String = ", ", prefix: String = "", postfix: String = "", limit: Int = -1, truncated: String = "...") : String {
val buffer = StringBuilder()
appendString(buffer, separator, prefix, postfix, limit, truncated)
return buffer.toString()
}
+25 -29
View File
@@ -1,21 +1,10 @@
package kotlin
import java.util.ArrayList
import java.util.HashMap
import java.util.HashSet
import java.util.LinkedList
/** Returns the string with leading and trailing text matching the given string removed */
public fun String.trim(text: String) : String = trimLeading(text).trimTrailing(text)
/** Returns the first character */
public fun String.first() : Char = this[0]
/** Returns the last character */
public fun String.last() : Char = this[length - 1]
public fun String.trim(text: String): String = trimLeading(text).trimTrailing(text)
/** Returns the string with the prefix and postfix text trimmed */
public fun String.trim(prefix: String, postfix: String) : String = trimLeading(prefix).trimTrailing(postfix)
public fun String.trim(prefix: String, postfix: String): String = trimLeading(prefix).trimTrailing(postfix)
/** Returns the string with the leading prefix of this string removed */
public fun String.trimLeading(prefix: String): String {
@@ -36,12 +25,12 @@ public fun String.trimTrailing(postfix: String): String {
}
/** Returns true if the string is not null and not empty */
public fun String?.isNotEmpty() : Boolean = this != null && this.length() > 0
public fun String?.isNotEmpty(): Boolean = this != null && this.length() > 0
/**
Iterator for characters of given CharSequence
*/
public fun CharSequence.iterator() : CharIterator = object : CharIterator() {
* Iterator for characters of given CharSequence
*/
public fun CharSequence.iterator(): CharIterator = object : CharIterator() {
private var index = 0
public override fun nextChar(): Char = get(index++)
@@ -55,20 +44,27 @@ public fun String?.orEmpty(): String = this ?: ""
// "Extension functions" for CharSequence
val CharSequence.size : Int
get() = this.length
public val CharSequence.size: Int
get() = this.length
public val String.size: Int
get() = length()
public val String.indices : IntRange
get() = 0..size
/**
* Counts the number of characters which match the given predicate
*
* @includeFunctionBody ../../test/text/StringTest.kt count
* Returns a subsequence specified by given set of indices.
*/
public inline fun String.count(predicate: (Char) -> Boolean): Int {
var answer = 0
for (c in this) {
if (predicate(c)) {
answer++
}
public fun CharSequence.slice(indices: Iterable<Int>): CharSequence {
val result = StringBuilder()
for (i in indices) {
result.append(get(i))
}
return answer
return result.toString()
}
/**
* Returns a substring specified by given range
*/
public fun String.substring(range: IntRange): String = substring(range.start, range.end + 1)
+101 -359
View File
@@ -8,173 +8,174 @@ import java.util.LinkedList
import java.util.Locale
import java.nio.charset.Charset
public inline fun String.lastIndexOf(str: String) : Int = (this as java.lang.String).lastIndexOf(str)
public fun String.lastIndexOf(str: String): Int = (this as java.lang.String).lastIndexOf(str)
public inline fun String.lastIndexOf(ch: Char) : Int = (this as java.lang.String).lastIndexOf(ch.toString())
public fun String.lastIndexOf(ch: Char): Int = (this as java.lang.String).lastIndexOf(ch.toString())
public inline fun String.equalsIgnoreCase(anotherString: String) : Boolean = (this as java.lang.String).equalsIgnoreCase(anotherString)
public fun String.equalsIgnoreCase(anotherString: String): Boolean = (this as java.lang.String).equalsIgnoreCase(anotherString)
public inline fun String.hashCode() : Int = (this as java.lang.String).hashCode()
public fun String.hashCode(): Int = (this as java.lang.String).hashCode()
public inline fun String.indexOf(str : String) : Int = (this as java.lang.String).indexOf(str)
public fun String.indexOf(str: String): Int = (this as java.lang.String).indexOf(str)
public inline fun String.indexOf(str : String, fromIndex : Int) : Int = (this as java.lang.String).indexOf(str, fromIndex)
public fun String.indexOf(str: String, fromIndex: Int): Int = (this as java.lang.String).indexOf(str, fromIndex)
public inline fun String.replace(oldChar: Char, newChar : Char) : String = (this as java.lang.String).replace(oldChar, newChar)
public fun String.replace(oldChar: Char, newChar: Char): String = (this as java.lang.String).replace(oldChar, newChar)
public inline fun String.replaceAll(regex: String, replacement : String) : String = (this as java.lang.String).replaceAll(regex, replacement)
public fun String.replaceAll(regex: String, replacement: String): String = (this as java.lang.String).replaceAll(regex, replacement)
public inline fun String.trim() : String = (this as java.lang.String).trim()
public fun String.trim(): String = (this as java.lang.String).trim()
public inline fun String.toUpperCase() : String = (this as java.lang.String).toUpperCase()
public fun String.toUpperCase(): String = (this as java.lang.String).toUpperCase()
public inline fun String.toLowerCase() : String = (this as java.lang.String).toLowerCase()
public fun String.toLowerCase(): String = (this as java.lang.String).toLowerCase()
public inline fun String.length() : Int = (this as java.lang.String).length()
public fun String.length(): Int = (this as java.lang.String).length()
public inline fun String.getBytes() : ByteArray = (this as java.lang.String).getBytes()
public fun String.getBytes(): ByteArray = (this as java.lang.String).getBytes()
public inline fun String.toCharArray() : CharArray = (this as java.lang.String).toCharArray()
public fun String.toCharArray(): CharArray = (this as java.lang.String).toCharArray()
public fun String.toCharList(): List<Char> = toCharArray().toList()
public fun String.format(vararg args: Any?): String = java.lang.String.format(this, *args)
public inline fun String.format(vararg args : Any?) : String = java.lang.String.format(this, *args)
public fun String.format(locale: Locale, vararg args : Any?) : String = java.lang.String.format(locale, this, *args)
public inline fun String.format(locale: Locale, vararg args : Any?) : String = java.lang.String.format(locale, this, *args)
public fun String.split(regex: String): Array<String> = (this as java.lang.String).split(regex)
public inline fun String.split(regex : String) : Array<String> = (this as java.lang.String).split(regex)
public fun String.split(ch: Char): Array<String> = (this as java.lang.String).split(java.util.regex.Pattern.quote(ch.toString()))
public inline fun String.split(ch : Char) : Array<String> = (this as java.lang.String).split(java.util.regex.Pattern.quote(ch.toString()))
public fun String.substring(beginIndex: Int): String = (this as java.lang.String).substring(beginIndex)
public inline fun String.substring(beginIndex : Int) : String = (this as java.lang.String).substring(beginIndex)
public fun String.substring(beginIndex: Int, endIndex: Int): String = (this as java.lang.String).substring(beginIndex, endIndex)
public inline fun String.substring(beginIndex : Int, endIndex : Int) : String = (this as java.lang.String).substring(beginIndex, endIndex)
public fun String.startsWith(prefix: String): Boolean = (this as java.lang.String).startsWith(prefix)
public inline fun String.startsWith(prefix: String) : Boolean = (this as java.lang.String).startsWith(prefix)
public fun String.startsWith(prefix: String, toffset: Int): Boolean = (this as java.lang.String).startsWith(prefix, toffset)
public inline fun String.startsWith(prefix: String, toffset: Int) : Boolean = (this as java.lang.String).startsWith(prefix, toffset)
public fun String.startsWith(ch: Char): Boolean = (this as java.lang.String).startsWith(ch.toString())
public inline fun String.startsWith(ch: Char) : Boolean = (this as java.lang.String).startsWith(ch.toString())
public fun String.contains(seq: CharSequence): Boolean = (this as java.lang.String).contains(seq)
public inline fun String.contains(seq: CharSequence) : Boolean = (this as java.lang.String).contains(seq)
public fun String.endsWith(suffix: String): Boolean = (this as java.lang.String).endsWith(suffix)
public inline fun String.endsWith(suffix: String) : Boolean = (this as java.lang.String).endsWith(suffix)
public inline fun String.endsWith(ch: Char) : Boolean = (this as java.lang.String).endsWith(ch.toString())
public fun String.endsWith(ch: Char): Boolean = (this as java.lang.String).endsWith(ch.toString())
// "constructors" for String
public inline fun String(bytes : ByteArray, offset : Int, length : Int, charsetName : String) : String = java.lang.String(bytes, offset, length, charsetName) as String
public fun String(bytes: ByteArray, offset: Int, length: Int, charsetName: String): String = java.lang.String(bytes, offset, length, charsetName) as String
public inline fun String(bytes : ByteArray, offset : Int, length : Int, charset : Charset) : String = java.lang.String(bytes, offset, length, charset) as String
public fun String(bytes: ByteArray, offset: Int, length: Int, charset: Charset): String = java.lang.String(bytes, offset, length, charset) as String
public inline fun String(bytes : ByteArray, charsetName : String) : String = java.lang.String(bytes, charsetName) as String
public fun String(bytes: ByteArray, charsetName: String): String = java.lang.String(bytes, charsetName) as String
public inline fun String(bytes : ByteArray, charset : Charset) : String = java.lang.String(bytes, charset) as String
public fun String(bytes: ByteArray, charset: Charset): String = java.lang.String(bytes, charset) as String
public inline fun String(bytes : ByteArray, i : Int, i1 : Int) : String = java.lang.String(bytes, i, i1) as String
public fun String(bytes: ByteArray, i: Int, i1: Int): String = java.lang.String(bytes, i, i1) as String
public inline fun String(bytes : ByteArray) : String = java.lang.String(bytes) as String
public fun String(bytes: ByteArray): String = java.lang.String(bytes) as String
public inline fun String(chars : CharArray) : String = java.lang.String(chars) as String
public fun String(chars: CharArray): String = java.lang.String(chars) as String
public inline fun String(stringBuffer : java.lang.StringBuffer) : String = java.lang.String(stringBuffer) as String
public fun String(stringBuffer: java.lang.StringBuffer): String = java.lang.String(stringBuffer) as String
public inline fun String(stringBuilder : java.lang.StringBuilder) : String = java.lang.String(stringBuilder) as String
public fun String(stringBuilder: java.lang.StringBuilder): String = java.lang.String(stringBuilder) as String
public inline fun String.replaceFirst(regex : String, replacement : String) : String = (this as java.lang.String).replaceFirst(regex, replacement)
public fun String.replaceFirst(regex: String, replacement: String): String = (this as java.lang.String).replaceFirst(regex, replacement)
public inline fun String.charAt(index : Int) : Char = (this as java.lang.String).charAt(index)
public fun String.charAt(index: Int): Char = (this as java.lang.String).charAt(index)
public inline fun String.split(regex : String, limit : Int) : Array<String> = (this as java.lang.String).split(regex, limit)
public fun String.split(regex: String, limit: Int): Array<String> = (this as java.lang.String).split(regex, limit)
public inline fun String.codePointAt(index : Int) : Int = (this as java.lang.String).codePointAt(index)
public fun String.codePointAt(index: Int): Int = (this as java.lang.String).codePointAt(index)
public inline fun String.codePointBefore(index : Int) : Int = (this as java.lang.String).codePointBefore(index)
public fun String.codePointBefore(index: Int): Int = (this as java.lang.String).codePointBefore(index)
public inline fun String.codePointCount(beginIndex : Int, endIndex : Int) : Int = (this as java.lang.String).codePointCount(beginIndex, endIndex)
public fun String.codePointCount(beginIndex: Int, endIndex: Int): Int = (this as java.lang.String).codePointCount(beginIndex, endIndex)
public inline fun String.compareToIgnoreCase(str : String) : Int = (this as java.lang.String).compareToIgnoreCase(str)
public fun String.compareToIgnoreCase(str: String): Int = (this as java.lang.String).compareToIgnoreCase(str)
public inline fun String.concat(str : String) : String = (this as java.lang.String).concat(str)
public fun String.concat(str: String): String = (this as java.lang.String).concat(str)
public inline fun String.contentEquals(cs : CharSequence) : Boolean = (this as java.lang.String).contentEquals(cs)
public fun String.contentEquals(cs: CharSequence): Boolean = (this as java.lang.String).contentEquals(cs)
public inline fun String.contentEquals(sb : StringBuffer) : Boolean = (this as java.lang.String).contentEquals(sb)
public fun String.contentEquals(sb: StringBuffer): Boolean = (this as java.lang.String).contentEquals(sb)
public inline fun String.getBytes(charset : Charset) : ByteArray = (this as java.lang.String).getBytes(charset)
public fun String.getBytes(charset: Charset): ByteArray = (this as java.lang.String).getBytes(charset)
public inline fun String.getBytes(charsetName : String) : ByteArray = (this as java.lang.String).getBytes(charsetName)
public fun String.getBytes(charsetName: String): ByteArray = (this as java.lang.String).getBytes(charsetName)
public inline fun String.getChars(srcBegin : Int, srcEnd : Int, dst : CharArray, dstBegin : Int) : Unit = (this as java.lang.String).getChars(srcBegin, srcEnd, dst, dstBegin)
public fun String.getChars(srcBegin: Int, srcEnd: Int, dst: CharArray, dstBegin: Int): Unit = (this as java.lang.String).getChars(srcBegin, srcEnd, dst, dstBegin)
public inline fun String.indexOf(ch : Char) : Int = (this as java.lang.String).indexOf(ch.toString())
public fun String.indexOf(ch: Char): Int = (this as java.lang.String).indexOf(ch.toString())
public inline fun String.indexOf(ch : Char, fromIndex : Int) : Int = (this as java.lang.String).indexOf(ch.toString(), fromIndex)
public fun String.indexOf(ch: Char, fromIndex: Int): Int = (this as java.lang.String).indexOf(ch.toString(), fromIndex)
public inline fun String.intern() : String = (this as java.lang.String).intern()
public fun String.intern(): String = (this as java.lang.String).intern()
public inline fun String.isEmpty() : Boolean = (this as java.lang.String).isEmpty()
public fun String.isEmpty(): Boolean = (this as java.lang.String).isEmpty()
public inline fun String.lastIndexOf(ch : Char, fromIndex : Int) : Int = (this as java.lang.String).lastIndexOf(ch.toString(), fromIndex)
public fun String.lastIndexOf(ch: Char, fromIndex: Int): Int = (this as java.lang.String).lastIndexOf(ch.toString(), fromIndex)
public inline fun String.lastIndexOf(str : String, fromIndex : Int) : Int = (this as java.lang.String).lastIndexOf(str, fromIndex)
public fun String.lastIndexOf(str: String, fromIndex: Int): Int = (this as java.lang.String).lastIndexOf(str, fromIndex)
public inline fun String.matches(regex : String) : Boolean = (this as java.lang.String).matches(regex)
public fun String.matches(regex: String): Boolean = (this as java.lang.String).matches(regex)
public inline fun String.offsetByCodePoints(index : Int, codePointOffset : Int) : Int = (this as java.lang.String).offsetByCodePoints(index, codePointOffset)
public fun String.offsetByCodePoints(index: Int, codePointOffset: Int): Int = (this as java.lang.String).offsetByCodePoints(index, codePointOffset)
public inline fun String.regionMatches(ignoreCase : Boolean, toffset : Int, other : String, ooffset : Int, len : Int) : Boolean = (this as java.lang.String).regionMatches(ignoreCase, toffset, other, ooffset, len)
public fun String.regionMatches(ignoreCase: Boolean, toffset: Int, other: String, ooffset: Int, len: Int): Boolean = (this as java.lang.String).regionMatches(ignoreCase, toffset, other, ooffset, len)
public inline fun String.regionMatches(toffset : Int, other : String, ooffset : Int, len : Int) : Boolean = (this as java.lang.String).regionMatches(toffset, other, ooffset, len)
public fun String.regionMatches(toffset: Int, other: String, ooffset: Int, len: Int): Boolean = (this as java.lang.String).regionMatches(toffset, other, ooffset, len)
public inline fun String.replace(target : CharSequence, replacement : CharSequence) : String = (this as java.lang.String).replace(target, replacement)
public fun String.replace(target: CharSequence, replacement: CharSequence): String = (this as java.lang.String).replace(target, replacement)
public inline fun String.subSequence(beginIndex : Int, endIndex : Int) : CharSequence = (this as java.lang.String).subSequence(beginIndex, endIndex)
public fun String.subSequence(beginIndex: Int, endIndex: Int): CharSequence = (this as java.lang.String).subSequence(beginIndex, endIndex)
public inline fun String.toLowerCase(locale : java.util.Locale) : String = (this as java.lang.String).toLowerCase(locale)
public fun String.toLowerCase(locale: java.util.Locale): String = (this as java.lang.String).toLowerCase(locale)
public inline fun String.toUpperCase(locale : java.util.Locale) : String = (this as java.lang.String).toUpperCase(locale)
public fun String.toUpperCase(locale: java.util.Locale): String = (this as java.lang.String).toUpperCase(locale)
public fun CharSequence.charAt(index: Int): Char = (this as java.lang.CharSequence).charAt(index)
public inline fun CharSequence.charAt(index : Int) : Char = (this as java.lang.CharSequence).charAt(index)
public fun CharSequence.subSequence(start: Int, end: Int): CharSequence? = (this as java.lang.CharSequence).subSequence(start, end)
public fun CharSequence.get(index : Int) : Char = charAt(index)
public fun CharSequence.toString(): String? = (this as java.lang.CharSequence).toString()
public inline fun CharSequence.subSequence(start : Int, end : Int) : CharSequence? = (this as java.lang.CharSequence).subSequence(start, end)
public fun CharSequence.length(): Int = (this as java.lang.CharSequence).length()
public fun CharSequence.get(start : Int, end : Int) : CharSequence? = subSequence(start, end)
public fun String.toByteArray(encoding: Charset): ByteArray = (this as java.lang.String).getBytes(encoding)
public inline fun CharSequence.toString() : String? = (this as java.lang.CharSequence).toString()
public inline fun CharSequence.length() : Int = (this as java.lang.CharSequence).length()
public fun String.toBoolean(): Boolean = java.lang.Boolean.parseBoolean(this)
public fun String.toShort(): Short = java.lang.Short.parseShort(this)
public fun String.toInt(): Int = java.lang.Integer.parseInt(this)
public fun String.toLong(): Long = java.lang.Long.parseLong(this)
public fun String.toFloat(): Float = java.lang.Float.parseFloat(this)
public fun String.toDouble(): Double = java.lang.Double.parseDouble(this)
public fun String.toCharList(): List<Char> = toCharArray().toList()
public fun CharSequence.get(index: Int): Char = charAt(index)
public fun CharSequence.get(start: Int, end: Int): CharSequence? = subSequence(start, end)
public fun String.toByteArray(encoding: String = Charset.defaultCharset().name()): ByteArray = (this as java.lang.String).getBytes(encoding)
public inline fun String.toByteArray(encoding: Charset): ByteArray = (this as java.lang.String).getBytes(encoding)
public inline fun String.toBoolean() : Boolean = java.lang.Boolean.parseBoolean(this)
public inline fun String.toShort() : Short = java.lang.Short.parseShort(this)
public inline fun String.toInt() : Int = java.lang.Integer.parseInt(this)
public inline fun String.toLong() : Long = java.lang.Long.parseLong(this)
public inline fun String.toFloat() : Float = java.lang.Float.parseFloat(this)
public inline fun String.toDouble() : Double = java.lang.Double.parseDouble(this)
/**
* Returns a subsequence specified by given range.
*/
public fun CharSequence.slice(range: IntRange): CharSequence {
return subSequence(range.start, range.end + 1)!! // inclusive
}
/**
* Converts the string into a regular expression [[Pattern]] optionally
* with the specified flags from [[Pattern]] or'd together
* so that strings can be split or matched on.
*/
public fun String.toRegex(flags: Int=0): java.util.regex.Pattern {
public fun String.toRegex(flags: Int = 0): java.util.regex.Pattern {
return java.util.regex.Pattern.compile(this, flags)
}
val String.reader : StringReader
get() = StringReader(this)
val String.size : Int
get() = length()
val String.reader: StringReader
get() = StringReader(this)
/**
* Returns a copy of this string capitalised if it is not empty or already starting with an uppper case letter, otherwise returns this
@@ -200,108 +201,23 @@ public fun String.decapitalize(): String {
* @includeFunctionBody ../../test/text/StringTest.kt repeat
*/
public fun String.repeat(n: Int): String {
require(n >= 0, { "Cannot repeat string $n times" })
if (n < 0)
throw IllegalArgumentException("Value should be non-negative, but was $n")
var sb = StringBuilder()
val sb = StringBuilder()
for (i in 1..n) {
sb.append(this)
}
return sb.toString()
}
/**
* Filters characters which match the given predicate into new String object
*
* @includeFunctionBody ../../test/text/StringTest.kt filter
*/
public inline fun String.filter(predicate: (Char) -> Boolean): String = filterTo(StringBuilder(), predicate).toString()
/**
* Returns an Appendable containing all characters which match the given *predicate*
*
* @includeFunctionBody ../../test/text/StringTest.kt filter
*/
public inline fun <T: Appendable> String.filterTo(result: T, predicate: (Char) -> Boolean): T
{
for (с in this) if (predicate(с)) result.append(с)
return result
}
/**
* Filters characters which match the given predicate into new String object
*
* @includeFunctionBody ../../test/text/StringTest.kt filterNot
*/
public inline fun String.filterNot(predicate: (Char) -> Boolean): String = filterNotTo(StringBuilder(), predicate).toString()
/**
* Returns an Appendable containing all characters which do not match the given *predicate*
*
* @includeFunctionBody ../../test/text/StringTest.kt filterNot
*/
public inline fun <T: Appendable> String.filterNotTo(result: T, predicate: (Char) -> Boolean): T {
for (element in this) if (!predicate(element)) result.append(element)
return result
}
/**
* Reverses order of characters in a string
*
* @includeFunctionBody ../../test/text/StringTest.kt reverse
*/
public fun String.reverse(): String = StringBuilder(this).reverse().toString()
/**
* Performs the given *operation* on each character
*
* @includeFunctionBody ../../test/text/StringTest.kt forEach
*/
public inline fun String.forEach(operation: (Char) -> Unit) { for(c in this) operation(c) }
/**
* Returns *true* if all characters match the given *predicate*
*
* @includeFunctionBody ../../test/text/StringTest.kt all
*/
public inline fun String.all(predicate: (Char) -> Boolean): Boolean {
for(c in this) if(!predicate(c)) return false
return true
}
/**
* Returns *true* if any character matches the given *predicate*
*
* @includeFunctionBody ../../test/text/StringTest.kt any
*/
public inline fun String.any(predicate: (Char) -> Boolean): Boolean {
for (c in this) if (predicate(c)) return true
return false
}
/**
* Appends the string from all the characters separated using the *separator* and using the given *prefix* and *postfix* if supplied
*
* If a string could be huge you can specify a non-negative value of *limit* which will only show substring then it will
* a special *truncated* separator (which defaults to "..."
*
* @includeFunctionBody ../../test/text/StringTest.kt appendString
*/
public fun String.appendString(buffer: Appendable, separator: String = ", ", prefix: String = "", postfix: String = "", limit: Int = -1, truncated: String = "..."): Unit {
buffer.append(prefix)
var count = 0
for (c in this) {
if (++count > 1) buffer.append(separator)
if (limit < 0 || count <= limit) buffer.append(c) else break
}
if (limit >= 0 && count > limit) buffer.append(truncated)
buffer.append(postfix)
}
/**
* Returns the first character which matches the given *predicate* or *null* if none matched
*
* @includeFunctionBody ../../test/text/StringTest.kt find
*/
deprecated("Use firstOrNull instead")
public inline fun String.find(predicate: (Char) -> Boolean): Char? {
for (c in this) if (predicate(c)) return c
return null
@@ -312,150 +228,18 @@ public inline fun String.find(predicate: (Char) -> Boolean): Char? {
*
* @includeFunctionBody ../../test/text/StringTest.kt findNot
*/
deprecated("Use firstOrNull instead")
public inline fun String.findNot(predicate: (Char) -> Boolean): Char? {
for (c in this) if (!predicate(c)) return c
return null
}
/**
* Partitions this string into a pair of string
*
* @includeFunctionBody ../../test/text/StringTest.kt partition
*/
public inline fun String.partition(predicate: (Char) -> Boolean): Pair<String, String> {
val first = StringBuilder()
val second = StringBuilder()
for (c in this) {
if (predicate(c)) {
first.append(c)
} else {
second.append(c)
}
}
return Pair(first.toString(), second.toString())
}
/**
* Returns a new List containing the results of applying the given *transform* function to each character in this string
*
*/
public inline fun <R> String.map(transform: (Char) -> R): List<R> = mapTo(ArrayList<R>(), transform)
/**
* Transforms each character of this string with the given *transform* function and
* adds each return value to the given *result* collection
*
*/
public inline fun <R, C: MutableCollection<in R>> String.mapTo(result: C, transform: (Char) -> R): C {
for (c in this) result.add(transform(c))
return result
}
/**
* Returns the result of transforming each character to one or more values which are concatenated together into a single list
*
* @includeFunctionBody ../../test/text/StringTest.kt flatMap
*/
public inline fun <R> String.flatMap(transform: (Char) -> Collection<R>): Collection<R> = flatMapTo(ArrayList<R>(), transform)
/**
* Returns the result of transforming each character to one or more values which are concatenated together into a passed list
*
* @includeFunctionBody ../../test/text/StringTest.kt flatMap
*/
public inline fun <R> String.flatMapTo(result: MutableCollection<R>, transform: (Char) -> Collection<R>): Collection<R> {
for (c in this) result.addAll(transform(c))
return result
}
/**
* Folds all characters from left to right with the *initial* value to perform the operation on sequential pairs of characters
*
* @includeFunctionBody ../../test/text/StringTest.kt fold
*/
public inline fun <R> String.fold(initial: R, operation: (R, Char) -> R): R {
var answer = initial
for (c in this) answer = operation(answer, c)
return answer
}
/**
* Folds all characters from right to left with the *initial* value to perform the operation on sequential pairs of characters
*
* @includeFunctionBody ../../test/text/StringTest.kt foldRight
*/
public inline fun <R> String.foldRight(initial: R, operation: (Char, R) -> R): R = reverse().fold(initial, { x, y -> operation(y, x) })
/**
* Applies binary operation to all characters in a string, going from left to right.
* Similar to fold function, but uses the first character as initial value
*
* @includeFunctionBody ../../test/text/StringTest.kt reduce
*/
public inline fun String.reduce(operation: (Char, Char) -> Char): Char {
val iterator = this.iterator()
if (!iterator.hasNext()) {
throw UnsupportedOperationException("Empty string can't be reduced")
}
var result = iterator.next()
while (iterator.hasNext()) {
result = operation(result, iterator.next())
}
return result
}
/**
* Applies binary operation to all characters in a string, going from right to left.
* Similar to foldRight function, but uses the last character as initial value
*
* @includeFunctionBody ../../test/text/StringTest.kt reduceRight
*/
public inline fun String.reduceRight(operation: (Char, Char) -> Char): Char = reverse().reduce { x, y -> operation(y, x) }
/**
* Groups the characters in the string into a new [[Map]] using the supplied *toKey* function to calculate the key to group the characters by
*
* @includeFunctionBody ../../test/text/StringTest.kt groupBy
*/
public inline fun <K> String.groupBy(toKey: (Char) -> K): Map<K, String> = groupByTo<K>(HashMap<K, String>(), toKey)
/**
* Groups the characters in the string into the given [[Map]] using the supplied *toKey* function to calculate the key to group the characters by
*
* @includeFunctionBody ../../test/text/StringTest.kt groupBy
*/
public inline fun <K> String.groupByTo(result: MutableMap<K, String>, toKey: (Char) -> K): Map<K, String> {
for (c in this) {
val key = toKey(c)
val str = result.getOrElse(key) { "" }
result[key] = str + c
}
return result
}
/**
* Creates a new string from all the characters separated using the *separator* and using the given *prefix* and *postfix* if supplied.
*
* If a string could be huge you can specify a non-negative value of *limit* which will only show a substring then it will
* a special *truncated* separator (which defaults to "..."
*
* @includeFunctionBody ../../test/text/StringTest.kt makeString
*/
public fun String.makeString(separator: String = ", ", prefix: String = "", postfix: String = "", limit: Int = -1, truncated: String = "..."): String {
val buffer = StringBuilder()
appendString(buffer, separator, prefix, postfix, limit, truncated)
return buffer.toString()
}
/**
* Returns an Appendable containing the everything but the first characters that satisfy the given *predicate*
*
* @includeFunctionBody ../../test/text/StringTest.kt dropWhile
*/
public inline fun <T: Appendable> String.dropWhileTo(result: T, predicate: (Char) -> Boolean): T {
public inline fun <T : Appendable> String.dropWhileTo(result: T, predicate: (Char) -> Boolean): T {
var start = true
for (element in this) {
if (start && predicate(element)) {
@@ -468,62 +252,20 @@ public inline fun <T: Appendable> String.dropWhileTo(result: T, predicate: (Char
return result
}
/**
* Returns a new String containing the everything but the first characters that satisfy the given *predicate*
*
* @includeFunctionBody ../../test/text/StringTest.kt dropWhile
*/
public inline fun String.dropWhile(predicate: (Char) -> Boolean): String = dropWhileTo(StringBuilder(), predicate).toString()
/**
* Returns a string containing everything but the first *n* characters
*
* @includeFunctionBody ../../test/text/StringTest.kt drop
*/
public fun String.drop(n: Int): String = substring(Math.min(length, n))
/**
* Returns an Appendable containing the first characters that satisfy the given *predicate*
*
*
* @includeFunctionBody ../../test/text/StringTest.kt takeWhile
*/
public inline fun <T: Appendable> String.takeWhileTo(result: T, predicate: (Char) -> Boolean): T {
public inline fun <T : Appendable> String.takeWhileTo(result: T, predicate: (Char) -> Boolean): T {
for (c in this) if (predicate(c)) result.append(c) else break
return result
}
/**
* Returns a new String containing the first characters that satisfy the given *predicate*
*
* @includeFunctionBody ../../test/text/StringTest.kt takeWhile
*/
public inline fun String.takeWhile(predicate: (Char) -> Boolean): String = takeWhileTo(StringBuilder(), predicate).toString()
/**
* Returns a string containing the first *n* characters
*
* @includeFunctionBody ../../test/text/StringTest.kt take
*/
public fun String.take(n: Int): String = substring(0, Math.min(length, n))
/** Copies all characters into the given collection */
public fun <C: MutableCollection<in Char>> String.toCollection(result: C): C {
for (c in this) result.add(c)
return result
}
/** Copies all characters into a [[LinkedList]] */
public fun String.toLinkedList(): LinkedList<Char> = toCollection(LinkedList<Char>())
/** Copies all characters into a [[List]] */
public fun String.toList(): List<Char> = toCollection(ArrayList<Char>(this.length()))
/** Copies all characters into a [[Collection] */
deprecated("Use toList() instead.")
public fun String.toCollection(): Collection<Char> = toCollection(ArrayList<Char>(this.length()))
/** Copies all characters into a [[Set]] */
public fun String.toSet(): Set<Char> = toCollection(HashSet<Char>())
/** Returns a new String containing the everything but the leading whitespace characters */
public fun String.trimLeading(): String {
var count = 0
@@ -544,11 +286,11 @@ public fun String.trimTrailing(): String {
return if (count < this.length) substring(0, count) else this
}
/**
* Replaces every *regexp* occurence in the text with the value retruned by the given function *body* that can handle
* particular occurance using [[MatchResult]] provided.
*/
public fun String.replaceAll(regexp: String, body: (java.util.regex.MatchResult) -> String) : String {
/**
* Replaces every *regexp* occurence in the text with the value retruned by the given function *body* that can handle
* particular occurance using [[MatchResult]] provided.
*/
public fun String.replaceAll(regexp: String, body: (java.util.regex.MatchResult) -> String): String {
val sb = StringBuilder(this.length())
val p = regexp.toRegex()
val m = p.matcher(this)
@@ -558,7 +300,7 @@ public fun String.replaceAll(regexp: String, body: (java.util.regex.MatchResult)
sb.append(this, lastIdx, m.start())
sb.append(body(m.toMatchResult()))
lastIdx = m.end()
}
}
if (lastIdx == 0) {
return this;
+18 -11
View File
@@ -84,12 +84,6 @@ class StringJVMTest {
assertEquals("abcd", "a1b2c3d4".filterNot { it.isDigit() })
}
test fun reverse() {
assertEquals("dcba", "abcd".reverse())
assertEquals("4321", "1234".reverse())
assertEquals("", "".reverse())
}
test fun forEach() {
val data = "abcd1234"
var count = 0
@@ -227,11 +221,11 @@ class StringJVMTest {
}
test fun groupBy() {
// collect similar characters by their int code
val data = "ababaaabcd"
val result = data.groupBy { it.toInt() }
assertEquals(4, result.size)
assertEquals("bbb", result.get('b'.toInt()))
// group characters by their case
val data = "abAbaABcD"
val result = data.groupBy { it.isLowerCase() }
assertEquals(2, result.size)
assertEquals(listOf('a','b','b','a','c'), result.get(true))
}
test fun makeString() {
@@ -369,4 +363,17 @@ class StringJVMTest {
assertEquals("", result)
}
test fun slice() {
val iter = listOf(4, 3, 0, 1)
val builder = StringBuilder()
builder.append("ABCD")
builder.append("abcd")
// ABCDabcd
// 01234567
assertEquals("BCDabc", builder.slice(1..6))
assertEquals("baD", builder.slice(5 downTo 3))
assertEquals("aDAB", builder.slice(iter))
}
}
+15
View File
@@ -47,4 +47,19 @@ class StringTest {
assertEquals("abcd", "Abcd".decapitalize())
assertEquals("uRL", "URL".decapitalize())
}
test fun slice() {
val iter = listOf(4, 3, 0, 1)
// abcde
// 01234
assertEquals("bcd", "abcde".substring(1..3))
assertEquals("dcb", "abcde".slice(3 downTo 1))
assertEquals("edab", "abcde".slice(iter))
}
test fun reverse() {
assertEquals("dcba", "abcd".reverse())
assertEquals("4321", "1234".reverse())
assertEquals("", "".reverse())
}
}
@@ -95,7 +95,7 @@ fun aggregates(): List<GenericFunction> {
return count
"""
}
body(Maps, Collections, ArraysOfObjects, ArraysOfPrimitives) {
body(Strings, Maps, Collections, ArraysOfObjects, ArraysOfPrimitives) {
"return size"
}
}
@@ -324,7 +324,7 @@ fun aggregates(): List<GenericFunction> {
templates add f("foldRight(initial: R, operation: (T, R) -> R)") {
inline(true)
only(Lists, ArraysOfObjects, ArraysOfPrimitives)
only(Strings, Lists, ArraysOfObjects, ArraysOfPrimitives)
doc { "Accumulates value starting with *initial* value and applying *operation* from right to left to each element and current accumulator value" }
typeParam("R")
returns("R")
@@ -363,7 +363,7 @@ fun aggregates(): List<GenericFunction> {
templates add f("reduceRight(operation: (T, T) -> T)") {
inline(true)
only(Lists, ArraysOfObjects, ArraysOfPrimitives)
only(Strings, Lists, ArraysOfObjects, ArraysOfPrimitives)
doc { "Accumulates value starting with last element and applying *operation* from right to left to each element and current accumulator value" }
returns("T")
body {
@@ -15,7 +15,7 @@ fun elements(): List<GenericFunction> {
return indexOf(element) >= 0
"""
}
exclude(Lists, Collections)
exclude(Strings, Lists, Collections)
body(ArraysOfPrimitives, ArraysOfObjects) {
"""
return indexOf(element) >= 0
@@ -24,6 +24,7 @@ fun elements(): List<GenericFunction> {
}
templates add f("indexOf(element: T)") {
exclude(Strings)
doc { "Returns first index of *element*, or -1 if the collection does not contain element" }
returns("Int")
body {
@@ -69,6 +70,7 @@ fun elements(): List<GenericFunction> {
}
templates add f("lastIndexOf(element: T)") {
exclude(Strings) // has native implementation
doc { "Returns last index of *element*, or -1 if the collection does not contain element" }
returns("Int")
body {
@@ -143,7 +145,7 @@ fun elements(): List<GenericFunction> {
throw IndexOutOfBoundsException("Collection doesn't contain element at index")
"""
}
body(Lists, ArraysOfObjects, ArraysOfPrimitives) {
body(Strings, Lists, ArraysOfObjects, ArraysOfPrimitives) {
"""
return get(index)
"""
@@ -171,7 +173,7 @@ fun elements(): List<GenericFunction> {
}
"""
}
body(Lists, ArraysOfObjects, ArraysOfPrimitives) {
body(Strings, Lists, ArraysOfObjects, ArraysOfPrimitives) {
"""
if (size == 0)
throw IllegalArgumentException("Collection is empty")
@@ -200,7 +202,7 @@ fun elements(): List<GenericFunction> {
}
"""
}
body(Lists, ArraysOfObjects, ArraysOfPrimitives) {
body(Strings, Lists, ArraysOfObjects, ArraysOfPrimitives) {
"""
return if (size > 0) this[0] else null
"""
@@ -255,7 +257,7 @@ fun elements(): List<GenericFunction> {
}
"""
}
body(Lists, ArraysOfObjects, ArraysOfPrimitives) {
body(Strings, Lists, ArraysOfObjects, ArraysOfPrimitives) {
"""
if (size == 0)
throw IllegalArgumentException("Collection is empty")
@@ -283,8 +285,7 @@ fun elements(): List<GenericFunction> {
}
"""
}
include(Lists)
body(Lists, ArraysOfObjects, ArraysOfPrimitives) {
body(Strings, Lists, ArraysOfObjects, ArraysOfPrimitives) {
"""
return if (size > 0) this[size - 1] else null
"""
@@ -348,7 +349,7 @@ fun elements(): List<GenericFunction> {
}
"""
}
body(Lists, ArraysOfObjects, ArraysOfPrimitives) {
body(Strings, Lists, ArraysOfObjects, ArraysOfPrimitives) {
"""
if (size != 1)
throw IllegalArgumentException("Collection has ${bucks}size elements")
@@ -376,7 +377,7 @@ fun elements(): List<GenericFunction> {
}
"""
}
body(Lists, ArraysOfObjects, ArraysOfPrimitives) {
body(Strings, Lists, ArraysOfObjects, ArraysOfPrimitives) {
"""
if (size == 0)
return null
@@ -15,6 +15,7 @@ enum class Family {
Maps
ArraysOfObjects
ArraysOfPrimitives
Strings
}
enum class PrimitiveType(val name: String) {
@@ -30,7 +31,7 @@ enum class PrimitiveType(val name: String) {
class GenericFunction(val signature: String) : Comparable<GenericFunction> {
val defaultFamilies = array(Iterables, Streams, ArraysOfObjects, ArraysOfPrimitives)
val defaultFamilies = array(Iterables, Streams, ArraysOfObjects, ArraysOfPrimitives, Strings)
var toNullableT: Boolean = false
@@ -150,10 +151,12 @@ class GenericFunction(val signature: String) : Comparable<GenericFunction> {
Maps -> "Map<K,V>"
Streams -> "Stream<T>"
ArraysOfObjects -> "Array<T>"
Strings -> "String"
ArraysOfPrimitives -> primitive?.let { it.name() + "Array" } ?: throw IllegalArgumentException("Primitive array should specify primitive type")
else -> throw IllegalStateException("Invalid family")
}
fun String.renderType(): String {
val t = StringTokenizer(this, " \t\n,:()<>?.", true)
val answer = StringBuilder()
@@ -174,11 +177,18 @@ class GenericFunction(val signature: String) : Comparable<GenericFunction> {
PrimitiveType.Float -> "0.0f"
else -> "0"
}
"TCollection" -> {
when (f) {
Strings -> "Appendable"
else -> "MutableCollection<in T>".renderType()
}
}
"T" -> {
if (f == Maps)
"Map.Entry<K,V>"
else
primitive?.name() ?: token
when (f) {
Strings -> "Char"
Maps -> "Map.Entry<K,V>"
else -> primitive?.name() ?: token
}
}
else -> token
})
@@ -189,7 +199,7 @@ class GenericFunction(val signature: String) : Comparable<GenericFunction> {
fun effectiveTypeParams(): List<String> {
val types = ArrayList(typeParams)
if (primitive == null) {
if (primitive == null && f != Strings) {
val implicitTypeParameters = receiver.dropWhile { it != '<' }.drop(1).takeWhile { it != '>' }.split(",")
for (implicit in implicitTypeParameters.reverse()) {
if (!types.any { it.startsWith(implicit) }) {
@@ -28,7 +28,9 @@ fun filtering(): List<GenericFunction> {
"""
}
include(Collections)
body(Strings) { "return substring(Math.min(n, size))" }
returns(Strings) { "String"}
body(Collections, ArraysOfObjects, ArraysOfPrimitives) {
"""
if (n >= size)
@@ -60,6 +62,9 @@ fun filtering(): List<GenericFunction> {
"""
}
body(Strings) { "return substring(0, Math.min(n, size))" }
returns(Strings) { "String"}
doc(Streams) { "Returns a stream containing first *n* elements" }
returns(Streams) { "Stream<T>" }
body(Streams) {
@@ -105,6 +110,17 @@ fun filtering(): List<GenericFunction> {
"""
}
returns(Strings) { "String"}
body(Strings) {
"""
for (index in 0..length)
if (!predicate(get(index))) {
return substring(index)
}
return ""
"""
}
inline(false, Streams)
doc(Streams) { "Returns a stream containing all elements except first elements that satisfy the given *predicate*" }
returns(Streams) { "Stream<T>" }
@@ -142,6 +158,17 @@ fun filtering(): List<GenericFunction> {
"""
}
returns(Strings) { "String"}
body(Strings) {
"""
for (index in 0..length)
if (!predicate(get(index))) {
return substring(0, index)
}
return ""
"""
}
inline(false, Streams)
doc(Streams) { "Returns a stream containing first elements satisfying the given *predicate*" }
returns(Streams) { "Stream<T>" }
@@ -163,6 +190,13 @@ fun filtering(): List<GenericFunction> {
"""
}
returns(Strings) { "String"}
body(Strings) {
"""
return filterTo(StringBuilder(), predicate).toString()
"""
}
inline(false, Streams)
doc(Streams) { "Returns a stream containing all elements matching the given *predicate*" }
returns(Streams) { "Stream<T>" }
@@ -178,7 +212,7 @@ fun filtering(): List<GenericFunction> {
inline(true)
doc { "Appends all elements matching the given *predicate* into the given *collection*" }
typeParam("C: MutableCollection<in T>")
typeParam("C: TCollection")
returns("C")
body {
@@ -187,6 +221,18 @@ fun filtering(): List<GenericFunction> {
return collection
"""
}
doc(Strings) { "Appends all characters matching the given *predicate* to the given *collection*" }
body(Strings) {
"""
for (index in 0..length - 1) {
val element = get(index)
if (predicate(element)) destination.append(element)
}
return destination
"""
}
include(Maps)
}
@@ -201,6 +247,13 @@ fun filtering(): List<GenericFunction> {
"""
}
returns(Strings) { "String"}
body(Strings) {
"""
return filterNotTo(StringBuilder(), predicate).toString()
"""
}
inline(false, Streams)
doc(Streams) { "Returns a stream containing all elements not matching the given *predicate*" }
returns(Streams) { "Stream<T>" }
@@ -216,7 +269,7 @@ fun filtering(): List<GenericFunction> {
inline(true)
doc { "Appends all elements not matching the given *predicate* to the given *collection*" }
typeParam("C: MutableCollection<in T>")
typeParam("C: TCollection")
returns("C")
body {
@@ -225,11 +278,19 @@ fun filtering(): List<GenericFunction> {
return collection
"""
}
doc(Strings) { "Appends all characters not matching the given *predicate* to the given *collection*" }
body(Strings) {
"""
for (element in this) if (!predicate(element)) collection.append(element)
return collection
"""
}
include(Maps)
}
templates add f("filterNotNull()") {
exclude(ArraysOfPrimitives)
exclude(ArraysOfPrimitives, Strings)
doc { "Returns a list containing all elements that are not null" }
typeParam("T: Any")
returns("List<T>")
@@ -250,11 +311,11 @@ fun filtering(): List<GenericFunction> {
}
templates add f("filterNotNullTo(collection: C)") {
exclude(ArraysOfPrimitives)
exclude(ArraysOfPrimitives, Strings)
doc { "Appends all elements that are not null to the given *collection*" }
typeParam("C: MutableCollection<in T>")
typeParam("T: Any")
returns("C")
typeParam("C: TCollection")
typeParam("T: Any")
toNullableT = true
body {
"""
@@ -265,7 +326,7 @@ fun filtering(): List<GenericFunction> {
}
templates add f("slice(indices: Iterable<Int>)") {
only(Lists, ArraysOfPrimitives, ArraysOfObjects)
only(Strings, Lists, ArraysOfPrimitives, ArraysOfObjects)
doc { "Returns a list containing elements at specified positions" }
returns("List<T>")
body {
@@ -277,6 +338,17 @@ fun filtering(): List<GenericFunction> {
return list
"""
}
returns(Strings) { "String" }
body(Strings) {
"""
val result = StringBuilder()
for (i in indices) {
result.append(get(i))
}
return result.toString()
"""
}
}
return templates
@@ -6,6 +6,7 @@ fun generators(): List<GenericFunction> {
val templates = arrayListOf<GenericFunction>()
templates add f("plus(element: T)") {
exclude(Strings)
doc { "Returns a list containing all elements of original collection and then the given element" }
returns("List<T>")
body {
@@ -26,7 +27,7 @@ fun generators(): List<GenericFunction> {
}
templates add f("plus(collection: Iterable<T>)") {
exclude(Streams)
exclude(Strings, Streams)
doc { "Returns a list containing all elements of original collection and then all elements of the given *collection*" }
returns("List<T>")
body {
@@ -39,7 +40,7 @@ fun generators(): List<GenericFunction> {
}
templates add f("plus(array: Array<T>)") {
exclude(Streams)
exclude(Strings, Streams)
doc { "Returns a list containing all elements of original collection and then all elements of the given *collection*" }
returns("List<T>")
body {
@@ -99,9 +100,25 @@ fun generators(): List<GenericFunction> {
return Pair(first, second)
"""
}
returns(Strings) { "Pair<String, String>" }
body(Strings) {
"""
val first = StringBuilder()
val second = StringBuilder()
for (element in this) {
if (predicate(element)) {
first.append(element)
} else {
second.append(element)
}
}
return Pair(first.toString(), second.toString())
"""
}
}
templates add f("zip(collection: Iterable<R>)") {
templates add f("zip(other: Iterable<R>)") {
exclude(Streams)
doc {
"""
@@ -113,7 +130,7 @@ fun generators(): List<GenericFunction> {
body {
"""
val first = iterator()
val second = collection.iterator()
val second = other.iterator()
val list = ArrayList<Pair<T,R>>()
while (first.hasNext() && second.hasNext()) {
list.add(first.next() to second.next())
@@ -123,6 +140,27 @@ fun generators(): List<GenericFunction> {
}
}
templates add f("zip(other : String)") {
only(Strings)
doc {
"""
Returns a list of pairs built from characters of both strings with same indexes. List has length of shortest collection.
"""
}
returns("List<Pair<Char,Char>>")
body {
"""
val first = iterator()
val second = other.iterator()
val list = ArrayList<Pair<Char,Char>>()
while (first.hasNext() && second.hasNext()) {
list.add(first.next() to second.next())
}
return list
"""
}
}
templates add f("zip(array: Array<R>)") {
exclude(Streams)
doc {
@@ -10,7 +10,7 @@ fun guards(): List<GenericFunction> {
templates add f("requireNoNulls()") {
include(Lists)
exclude(ArraysOfPrimitives)
exclude(Strings, ArraysOfPrimitives)
doc { "Returns an original collection containing all the non-*null* elements, throwing an [[IllegalArgumentException]] if there are any null elements" }
typeParam("T:Any")
toNullableT = true
@@ -45,7 +45,8 @@ fun mapping(): List<GenericFunction> {
}
templates add f("mapNotNull(transform : (T) -> R)") {
exclude(ArraysOfPrimitives)
inline(true)
exclude(Strings, ArraysOfPrimitives)
doc { "Returns a list containing the results of applying the given *transform* function to each non-null element of the original collection" }
typeParam("T: Any")
typeParam("R")
@@ -59,6 +60,7 @@ fun mapping(): List<GenericFunction> {
doc(Streams) { "Returns a stream containing the results of applying the given *transform* function to each non-null element of the original stream" }
returns(Streams) { "Stream<R>" }
inline(false, Streams)
body(Streams) {
"""
return TransformingStream(FilteringStream(this, false, { it != null }) as Stream<T>, transform)
@@ -91,7 +93,7 @@ fun mapping(): List<GenericFunction> {
templates add f("mapNotNullTo(collection: C, transform : (T) -> R)") {
inline(true)
exclude(ArraysOfPrimitives)
exclude(Strings, ArraysOfPrimitives)
doc {
"""
Appends transformed non-null elements of original collection using the given *transform* function
@@ -16,6 +16,15 @@ fun ordering(): List<GenericFunction> {
"""
}
doc(Strings) { "Returns a string with characters in reversed order" }
returns(Strings) { "String"}
body(Strings) {
// TODO: Replace with StringBuilder(this) when JS can handle it
"""
return StringBuilder().append(this).reverse().toString()
"""
}
exclude(Streams)
}
@@ -38,6 +47,7 @@ fun ordering(): List<GenericFunction> {
exclude(Streams)
exclude(ArraysOfPrimitives) // TODO: resolve collision between inplace sort and this function
exclude(ArraysOfObjects)
exclude(Strings)
}
templates add f("sortDescending()") {
@@ -60,6 +70,7 @@ fun ordering(): List<GenericFunction> {
exclude(Streams)
exclude(ArraysOfPrimitives) // TODO: resolve collision between inplace sort and this function
exclude(ArraysOfObjects)
exclude(Strings)
}
templates add f("sortBy(order: (T) -> R)") {
@@ -83,6 +94,7 @@ fun ordering(): List<GenericFunction> {
exclude(Streams)
exclude(ArraysOfPrimitives)
exclude(Strings)
}
templates add f("sortDescendingBy(order: (T) -> R)") {
@@ -106,6 +118,7 @@ fun ordering(): List<GenericFunction> {
exclude(Streams)
exclude(ArraysOfPrimitives)
exclude(Strings)
}
templates add f("sortBy(comparator : Comparator<T>)") {
@@ -125,6 +138,7 @@ fun ordering(): List<GenericFunction> {
exclude(Streams)
exclude(ArraysOfPrimitives)
exclude(Strings)
}
return templates