package kotlin import java.util.* /** * Returns *true* if all elements match the given *predicate* * * @includeFunctionBody ../../test/CollectionTest.kt all */ public inline fun Iterable.all(predicate: (T) -> Boolean) : Boolean { for (element in this) if (!predicate(element)) return false return true } /** * Returns *true* if any elements match the given *predicate* * * @includeFunctionBody ../../test/CollectionTest.kt any */ public inline fun Iterable.any(predicate: (T) -> Boolean) : Boolean { for (element in this) if (predicate(element)) return true return false } /** * 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 "..." * * @includeFunctionBody ../../test/CollectionTest.kt appendString */ public inline fun Iterable.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) } /** * Returns the number of elements which match the given *predicate* * * @includeFunctionBody ../../test/CollectionTest.kt count */ public inline fun Iterable.count(predicate: (T) -> Boolean) : Int { var count = 0 for (element in this) if (predicate(element)) count++ return count } /** * Returns the first element which matches the given *predicate* or *null* if none matched * * @includeFunctionBody ../../test/CollectionTest.kt find */ public inline fun Iterable.find(predicate: (T) -> Boolean) : T? { for (element in this) if (predicate(element)) return element return null } /** * Filters all elements which match the given predicate into the given list * * @includeFunctionBody ../../test/CollectionTest.kt filterIntoLinkedList */ public inline fun > Iterable.filterTo(result: C, predicate: (T) -> Boolean) : C { for (element in this) if (predicate(element)) result.add(element) return result } /** * Partitions this collection into a pair of collection * * @includeFunctionBody ../../test/CollectionTest.kt partition */ public inline fun Iterable.partition(predicate: (T) -> Boolean) : Pair, List> { val first = ArrayList() val second = ArrayList() for (element in this) { if (predicate(element)) { first.add(element) } else { second.add(element) } } return Pair(first, second) } /** * Returns a list containing all elements which do not match the given *predicate* * * @includeFunctionBody ../../test/CollectionTest.kt filterNotIntoLinkedList */ public inline fun > Iterable.filterNotTo(result: C, predicate: (T) -> Boolean) : C { for (element in this) if (!predicate(element)) result.add(element) return result } /** * Filters all non-*null* elements into the given list * * @includeFunctionBody ../../test/CollectionTest.kt filterNotNullIntoLinkedList */ public inline fun > Iterable?.filterNotNullTo(result: C) : C { if (this != null) { for (element in this) if (element != null) result.add(element) } return result } /** * Returns the result of transforming each element to one or more values which are concatenated together into a single list * * @includeFunctionBody ../../test/CollectionTest.kt flatMap */ public inline fun Iterable.flatMapTo(result: MutableCollection, transform: (T) -> Collection) : Collection { for (element in this) { val list = transform(element) for (r in list) result.add(r) } return result } /** * Performs the given *operation* on each element * * @includeFunctionBody ../../test/CollectionTest.kt forEach */ public inline fun Iterable.forEach(operation: (T) -> Unit) : Unit = for (element in this) operation(element) /** * Folds all elements from from left to right with the *initial* value to perform the operation on sequential pairs of elements * * @includeFunctionBody ../../test/CollectionTest.kt fold */ public inline fun Iterable.fold(initial: R, operation: (R, T) -> R): R { var answer = initial for (element in this) answer = operation(answer, element) return answer } /** * Folds all elements from right to left with the *initial* value to perform the operation on sequential pairs of elements * * @includeFunctionBody ../../test/CollectionTest.kt foldRight */ public inline fun Iterable.foldRight(initial: R, operation: (T, R) -> R): R = reverse().fold(initial, {x, y -> operation(y, x)}) /** * Applies binary operation to all elements of iterable, going from left to right. * Similar to fold function, but uses the first element as initial value * * @includeFunctionBody ../../test/CollectionTest.kt reduce */ public inline fun Iterable.reduce(operation: (T, T) -> T): T { val iterator = this.iterator() if (!iterator.hasNext()) { throw UnsupportedOperationException("Empty iterable can't be reduced") } var result: T = iterator.next() //compiler doesn't understand that result will initialized anyway while (iterator.hasNext()) { result = operation(result, iterator.next()) } return result } /** * Applies binary operation to all elements of iterable, going from right to left. * Similar to foldRight function, but uses the last element as initial value * * @includeFunctionBody ../../test/CollectionTest.kt reduceRight */ public inline fun Iterable.reduceRight(operation: (T, T) -> T): T = reverse().reduce { x, y -> operation(y, x) } /** * Groups the elements in the collection into a new [[Map]] using the supplied *toKey* function to calculate the key to group the elements by * * @includeFunctionBody ../../test/CollectionTest.kt groupBy */ public inline fun Iterable.groupBy(toKey: (T) -> K) : Map> = groupByTo(HashMap>(), toKey) /** * Groups the elements in the collection into the given [[Map]] using the supplied *toKey* function to calculate the key to group the elements by * * @includeFunctionBody ../../test/CollectionTest.kt groupBy */ public inline fun Iterable.groupByTo(result: MutableMap>, toKey: (T) -> K) : Map> { for (element in this) { val key = toKey(element) val list = result.getOrPut(key) { ArrayList() } list.add(element) } return result } /** * 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 "..." * * @includeFunctionBody ../../test/CollectionTest.kt makeString */ public inline fun Iterable.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 a list containing the everything but the first elements that satisfy the given *predicate* */ public inline fun > Iterable.dropWhileTo(result: L, predicate: (T) -> Boolean) : L { var start = true for (element in this) { if (start && predicate(element)) { // ignore } else { start = false result.add(element) } } return result } /** Returns a list containing the first elements that satisfy the given *predicate* */ public inline fun > Iterable.takeWhileTo(result: C, predicate: (T) -> Boolean) : C { for (element in this) if (predicate(element)) result.add(element) else break return result } /** Copies all elements into the given collection */ public inline fun > Iterable.toCollection(result: C) : C { for (element in this) result.add(element) return result } /** * Reverses the order the elements into a list * * @includeFunctionBody ../../test/CollectionTest.kt reverse */ public inline fun Iterable.reverse() : List { val list = toCollection(ArrayList()) Collections.reverse(list) return list } /** Copies all elements into a [[LinkedList]] */ public inline fun Iterable.toLinkedList() : LinkedList = toCollection(LinkedList()) /** Copies all elements into a [[List]] */ public inline fun Iterable.toList() : List = toCollection(ArrayList()) /** Copies all elements into a [[List] */ public inline fun Iterable.toCollection() : Collection = toCollection(ArrayList()) /** Copies all elements into a [[Set]] */ public inline fun Iterable.toSet() : Set = toCollection(HashSet()) /** TODO figure out necessary variance/generics ninja stuff... :) public inline fun Iterable.toSortedList(transform: fun(T) : java.lang.Comparable<*>) : List { val answer = this.toList() answer.sort(transform) return answer } */