Kotlin snippets that you can understand quickly, using only stdlib functionality.

Overview

Support this and other projects from Ivan Mwiruki here.


Kotlin

30 seconds of Kotlin

Curated collection of useful Kotlin 1.3 snippets that you can understand quickly, using only stdlib functionality.

Snippets are optimized for readability and comprehension, sometimes at the expense of performance.

Note: This project is inspired by, but in no way affiliated with, 30 Seconds of Code.

Table of Contents

List

Functions operating on the most fundamental data structure: List.

View contents

Function

Kotlin's first class functions make it easy to manipulate functions.

View contents

Lazy

Functions operating on Kotlin's built in Lazy type.

View contents

Map

Functions operating on Maps.

View contents

Related projects


List

all

Returns true if the provided predicate function returns true for all elements in a list, false otherwise.

fun <T> all(list: List<T>, predicate: (T) -> Boolean): Boolean =
    list.all(predicate)

allEqual

Checks if all elements in a list are equal.

fun <T> allEqual(list: List<T>): Boolean =
    if (list.isEmpty()) false else list.all { it == list[0] }

any

Returns true if the provided predicate function returns true for at least one element in a list, false otherwise.

fun <T> any(list: List<T>, predicate: (T) -> Boolean): Boolean =
    list.any(predicate)

bifurcate

Splits list into two groups. For every element in a list, if the corresponding boolean in another list is true, add the element to the first group; otherwise, add it to the second group.

// For example:
bifurcate(listOf("beep", "boop", "foo", "bar"), listOf(true, true, false, true)) // [[beep, boop, bar], [foo]]
fun <T> bifurcate(list: List<T>, filter: List<Boolean>): Pair<List<T>, List<T>> {
    require(list.size == filter.size)
    return list.zip(filter).partition { it.second }
        .let { (list1, list2) -> list1.map { it.first } to list2.map { it.first } }
}

bifurcateBy

Splits values into two groups according to a predicate function, which specifies which group an element in the input list belongs to. If the predicate function returns true, the list element belongs to the first group; otherwise, it belongs to the second group.

fun <T> bifurcateBy(list: List<T>, predicate: (T) -> Boolean): Pair<List<T>, List<T>> =
    list.partition(predicate)

chunk

Chunks a list into smaller lists of a specified size. The last list in the resulting list may have less elements than the given size.

// For example:
chunk(listOf(1, 2, 3, 4, 5), 2) // [[1 ,2], [3, 4], [5]]
fun <T> chunk(list: List<T>, size: Int): List<List<T>> =
    list.chunked(size)

compact

Removes "falsey" values from a list.

Kotlin doesn't distinguish falsey values but they are (false, null, 0, "", [], and NaN).

fun <T> compact(list: List<T?>): List<T> {
    fun isTruthy(t: T?): Boolean = when(t) {
        null -> false
        is Boolean -> t
        is Double -> t != Double.NaN
        is Number -> t.toInt() != 0
        is String -> !t.isEmpty()
        is Array<*> -> t.size != 0
        is Collection<*> -> !t.isEmpty()
        else -> true
    }
    @Suppress("UNCHECKED_CAST")
    return list.filter(::isTruthy) as List<T>
}

countBy

Groups the elements of a list based on the given function and returns the count of elements in each group.

// For example:
countBy(listOf(6.1, 4.2, 6.3)) { floor(it) } // {4.0: 1, 6.0: 2}
countBy(listOf("one", "two", "three")) { it.length } // {3: 2, 5: 1}
fun <T, K> countBy(list: List<T>, function: (T) -> K): Map<K, Int> =
    list.groupingBy(function).eachCount()

countOccurrences

Counts the occurrences of a value in a list, using a provided equality function.

fun <T> countOccurrences(list: List<T>, target: T, equals: (T, T) -> Boolean = Objects::equals): Int =
    list.count { equals(target, it) }

concat

Concatenates multiple lists into a single list, preserving the order of the passed in elements.

fun <T> concat(first: List<T>, vararg others: List<T>): List<T> =
    first.asSequence().plus(others.asSequence().flatten()).toList()

corresponds

Tests whether every element of the first list relates to the corresponding element in the second list by satisfying the given predicate.

// For example:
corresponds(listOf(1, 2, 3), listOf(2, 3, 4)) { i1, i2 -> i1 == i2 - 1 } // true
fun <T, U> corresponds(first: List<T>, second: List<U>, predicate: (T, U) -> Boolean): Boolean =
    (first.size == second.size) && (first.zip(second).all { (t, u) -> predicate(t, u) })

crossProduct

Creates a cross product: forming a pair from each value in the first list to each value in the second list.

// For example:
crossProduct(listOf(1, 2), listOf('a', 'b')) // [[1, 'a'], [1, 'b'], [2, 'a'], [2, 'b']]
fun <T, U> crossProduct(first: List<T>, second: List<U>): List<Pair<T, U>> =
    first.flatMap { a -> second.map { b -> a to b } }

cycle

Produces a Sequence which cycles indefinitely through the given list.

// For example:
cycle(listOf(1, 2, 3)) // 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3...
fun <T> cycle(list: List<T>): Sequence<T> = 
    generateSequence(if (list.isNotEmpty()) 0 else null) { (it + 1) % list.size }
        .map { list[it] }

difference

Returns a list of elements contained in the first list that are not present in the second list.

// For example:
difference(listOf(1, 2, 3), listOf(1, 2, 4)) // [3]
fun <T> difference(first: List<T>, second: List<T>): List<T> =
    (first subtract second).toList()

differenceBy

Returns a list of elements contained in the first list that are not present in the second list, after applying the provided function to each list element of both.

fun <T, R> differenceBy(first: List<T>, second: List<T>, function: (T) -> R): List<T> =
    with(second.toSet().map(function)) {
        first.filterNot { contains(function(it)) }
    }

differenceWith

Filters out all elements from the first list for which the comparator function does not return true for that element and every element in the second list.

fun <T> differenceWith(first: List<T>, second: List<T>, function: (T, T) -> Boolean): List<T> =
    first.filter { a -> second.none { b -> function(a, b) } }

distinct

Returns all distinct elements.

fun <T> distinct(list: List<T>): List<T> =
    list.distinct()

drop

Returns a new list with n elements removed from the left.

fun <T> drop(list: List<T>, n: Int): List<T> =
    list.drop(n)

dropRight

Returns a new list with n elements removed from the right.

fun <T> dropRight(list: List<T>, n: Int): List<T> =
    list.dropLast(n)

dropRightWhile

Removes elements from the end of a list until the passed function returns true. Returns the remaining elements in the list.

fun <T> dropRightWhile(list: List<T>, predicate: (T) -> Boolean): List<T> =
    list.dropLastWhile(predicate)

dropWhile

Removes elements from the beginning of a list until the passed function returns true. Returns the remaining elements in the list.

fun <T> dropWhile(list: List<T>, predicate: (T) -> Boolean): List<T> =
    list.dropWhile(predicate)

endsWith

Checks whether the given list ends with the given sublist.

fun <T> endsWith(list: List<T>, subList: List<T>): Boolean =
    list.takeLast(subList.size) == subList

everyNth

Returns every nth element in a list.

// For example:
everyNth(listOf(1, 2, 3, 4, 5, 6), 2) // [ 2, 4, 6 ]
fun <T> everyNth(list: List<T>, nth: Int): List<T> =
    list.windowed(nth, nth, partialWindows = false).map { it.last() }

existsUnique

Checks if a unique element exists such that the predicate holds.

// For example:
existsUnique(listOf(1, 2, 3, 4, 5, 3)) { it == 3 } // false
fun <T> existsUnique(list: List<T>, predicate: (T) -> Boolean): Boolean {
    var exists = false
    for (t in list) {
        if (predicate(t)) {
            if (exists) {
                return false
            } else {
                exists = true
            }
        }
    }
    return exists
}

filterNonUnique

Filters out the non-unique values in a list.

fun <T> filterNonUnique(list: List<T>): List<T> =
    list.distinct()

filterNonUniqueBy

Filters out the non-unique values in an list, after applying the given function.

// For example: 
filterNonUniqueBy(listOf('a', 'b', 'c')) { 1 } // [a]
fun <T, K> filterNonUniqueBy(list: List<T>, function: (T) -> K): List<T> =
    list.distinctBy(function)

findLast

Returns the last element for which the provided function returns true, or null if none is found.

fun <T> findLast(list: List<T>, predicate: (T) -> Boolean): T? =
    list.findLast(predicate)

findLastIndex

Returns the index of the last element for which the provided function returns true, or -1 if none is found.

fun <T> findLastIndex(list: List<T>, predicate: (T) -> Boolean): Int =
    list.indexOfLast(predicate)

forEachRight

Executes a provided function once for each list element, starting from the list's last element.

fun <T> forEachRight(list: List<T>, action: (T) -> Unit): Unit =
    list.reversed().forEach(action)

groupBy

Groups the elements of a list based on the given function.

// For example:
groupBy(listOf(6.1, 4.2, 6.3)) { floor(it) } // {4.0: [4.2], 6.0: [6.1, 6.3]}
groupBy(listOf("one", "two", "three")) { it.length } // {3: [one, two], 5: [three]}
fun <T, K> groupBy(list: List<T>, function: (T) -> K): Map<K, List<T>> =
    list.groupBy(function)

hasDuplicates

Returns true if duplicate values exist in the list, false otherwise.

fun <T> hasDuplicates(list: List<T>): Boolean =
    list.toSet().size != list.size

hasSubList

Checks whether the given list contains the given sublist.

tailrec fun <T> hasSubList(list: List<T>, subList: List<T>): Boolean =
    when {
        subList.isEmpty() -> true
        list.isEmpty() -> subList.isEmpty()
        list.take(subList.size) == subList -> true
        else -> hasSubList(list.drop(1), subList)
    }

head

Returns the head of a list.

fun <T> head(list: List<T>): T =
    list.first()

indexOfAll

Returns all indices in a list where a given value is present. If the value never occurs, returns an empty list.

// For example:
indexOfAll(listOf(1, 2, 3, 1, 2, 3), 1) // [0, 3]
indexOfAll(listOf(1, 2, 3), 4) // []
fun <T> indexOfAll(list: List<T>, target: T): List<Int> =
    list.withIndex().filter { it.value == target }.map { it.index }

initial

Returns all the elements of an array except the last one.

fun <T> initial(list: List<T>): List<T> =
    list.dropLast(1)

initialize2DList

Initializes a 2D list of given width and height and value.

// For exmaple:
initialize2DList(2, 2, 0) // [[0, 0], [0, 0]]
fun <T> initialize2DList(width: Int, height: Int, value: T): List<List<T>> =
    List(height) { List(width) { value } }

initializeListWithRange

Initializes a list containing the numbers in the specified range, where start and stop are inclusive with their common difference step.

// For example:
initializeListWithRange(0, 9, 2) // [0, 2, 4, 6, 8]
fun initializeListWithRange(start: Int, stop: Int, step: Int): List<Int> =
    (start..stop step step).toList()

initializeListWithValue

Initializes and fills a list with the specified value.

// For example:
initializeListWithValue(5, 2) // [2, 2, 2, 2, 2]
fun <T> initializeListWithValue(size: Int, value: T): List<T> =
    List(size) { value }

intersection

Returns a list of elements that exist in both lists.

// For example:
intersection(listOf(1, 2, 3), listOf(4, 3, 2)) // [2, 3]
fun <T> intersection(first: List<T>, second: List<T>): List<T> =
    (first intersect second).toList()

intersectionBy

Returns a list of elements that exist in both lists, after applying the provided function to each element of both.

// For example:
intersectionBy(listOf(2.1, 1.2), listOf(2.3, 3.4)) { floor(it) } // [2.1]
fun <T, R> intersectionBy(first: List<T>, second: List<T>, function: (T) -> R): List<T> =
    with(second.toSet().map(function)) {
        first.filter { contains(function(it)) }
    }

intersectionWith

Returns a list of elements that exist in both lists, using a provided comparator function.

// For example:
intersectionWith(listOf(1.0, 1.2, 1.5, 3.0, 0.0), listOf(1.9, 3.0, 0.0, 3.9)) { a, b -> round(a) == round(b) } // [1.5, 3.0, 0.0]
fun <T> intersectionWith(first: List<T>, second: List<T>, function: (T, T) -> Boolean): List<T> =
    first.filter { a -> second.any { b -> function(a, b) } }

intersperse

Inserts an element between all elements of the given list.

// For example:
intersperse(listOf('a', 'b', 'c', 'd'), '0') // [a, 0, b, 0, c, 0, d]
fun <T> intersperse(list: List<T>, element: T): List<T> =
    List(list.size) { index -> listOf(list[index], element) }.flatten().dropLast(1)

join

Joins all elements of a list into a string.

fun <T> join(list: List<T>, separator: String = ", "): String =
    list.joinToString(separator)

last

Returns the last element of a list.

fun <T> last(list: List<T>): T =
    list.last()

longest

Returns the longest collection in the list, or null if the list has no collections. If multiple collections have the same size, the first one will be returned.

fun <T> longest(list: List<Collection<T>>): Collection<T>? = 
    list.maxBy { it.size }

mapObject

Maps the elements of a list to the result of applying a function to that element.

// For example:
mapObject(listOf(1, 2, 3)) { it * it } // { 1: 1, 2: 4, 3: 9 }
fun <T, R> mapObject(list: List<T>, function: (T) -> R): Map<T, R> =
    list.associateWith(function)

maxN

Returns the n maximum elements from the provided list. If n is greater than or equal to the provided list's length, then return the original list (sorted in descending order).

fun <T : Comparable<T>> maxN(list: List<T>, n: Int): List<T> =
    list.sortedDescending().take(n)

minN

Returns the n minimum elements from the provided list. If n is greater than or equal to the provided list's length, then return the original list (sorted in ascending order).

fun <T : Comparable<T>> minN(list: List<T>, n: Int): List<T> =
    list.sorted().take(n)

none

Returns true if the provided predicate function returns false for all elements in a list, false otherwise.

// For example:
none(listOf(0, 1, 3, 0)) { it == 2} // true
none(listOf(-1, 1, 2)) { it <= 0 } // false
fun <T> none(list: List<T>, predicate: (T) -> Boolean): Boolean =
    list.none(predicate)

nthElement

Returns the nth element of a list. If the index is out of bounds, throws IndexOutOfBoundsException.

fun <T> nthElement(list: List<T>, n: Int): T =
   list[n]

partition

Groups the elements into two lists, the first containing all elements for which the predicate evaluated to true, and the second containing all other elements.

fun <T> partition(list: List<T>, predicate: (T) -> Boolean): Pair<List<T>, List<T>> =
    list.partition(predicate)

partitioningBy

Partitions the input elements according to a predicate and organizes them into a Map<Boolean, List<T>. Inspired by the JDK's Collectors::partitioningBy.

fun <T> partitioningBy(list: List<T>, predicate: (T) -> Boolean): Map<Boolean, List<T>> = 
    list.groupBy(predicate)

permutations

Computes all the permutations of the given list. List elements are treated unique based on their index, so a list with equal elements will return duplicate lists.

Note: this implementation uses non stack safe recursion

kotlin // For example: permutations(listOf(1, 2, 3)) // [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]

fun <T> permutations(list: List<T>): List<List<T>> {
    fun <T> List<T>.removeAtIndex(index: Int): List<T> = take(index) + drop(index + 1)
    fun <T> List<T>.prepend(element: T): List<T> = listOf(element) + this
    return  when {
        list.isEmpty() -> emptyList()
        list.size == 1 -> listOf(list)
        else -> list.foldIndexed(mutableListOf()) { index, acc, t ->
            acc.apply {
                addAll(permutations(list.removeAtIndex(index)).map { it.prepend(t) })
            }
        }
    }
}

product

Creates a cross product: applying the provided function to each value in the first list along with each value in the second list

fun <T, U, R> product(first: List<T>, second: List<U>, function: (T, U) -> R): List<R> =
    first.flatMap { t -> second.map { u -> function(t, u) } }

pull

Filters out the elements specified.

// For example:
pull(listOf('a', 'b', 'c', 'a', 'b', 'c'), 'a', 'c') // [b, b]
fun <T> pull(list: List<T>, vararg elements: T): List<T> =
    with(elements.toSet()) {
       list.filterNot { contains(it) }
    }

pullAtIndex

Filters out the indices specified.

// For example:
pullAtIndex(listOf('a', 'b', 'c', 'd'), 1, 2) // [a, d] 
fun <T> pullAtIndex(list: List<T>, vararg indices: Int): List<T> =
    with(indices.toSet()) {
        list.filterIndexed { index, _ -> !contains(index) }
    }

pullAtValue

Filters out the elements specified and returns them.

// For example:
pullAtValue(listOf('a', 'b', 'c', 'd'), 'b', 'd', 'e') // [b, d]
fun <T> pullAtValue(list: List<T>, vararg elements: T): List<T> =
    with(elements.toSet()) {
        list.filter { contains(it) }
    }

reduceSuccessive

This function is also commonly known as scan. Applies a function against an accumulator and each element in the list (from left to right), returning a new list of successively calculated values.

// For example:
reduceSuccessive(listOf(1, 2, 3, 4, 5, 6), 0) { acc, int -> acc + int } // [1, 3, 6, 10, 15, 21]
fun <T, R> reduceSuccessive(list: List<T>, identity: R, function: (R, T) -> R): List<R> {
    fun <T> List<T>.lastOrElse(t: T): T = lastOrNull() ?: t
    return list.fold(emptyList()) { acc, t -> acc + function(acc.lastOrElse(identity), t) }
}

reject

Return a new list which removes elements from the list for which the given predicate returns true.

// For example:
reject(listOf(1, 2, 3, 4, 5)) { it % 2 == 0 } // [1, 3, 5]
reject(listOf("Apple", "Pear", "Kiwi", "Banana")) { it.length > 4 } // [Pear, Kiwi]
fun <T> reject(list: List<T>, predicate: (T) -> Boolean): List<T> =
    list.filterNot(predicate)

remove

Returns a new list which removes elements from the list for which the given predicate returns false.

// For example:
remove(listOf(1, 2, 3, 4)) { it % 2 == 0 } // [2, 4]
fun <T> remove(list: List<T>, predicate: (T) -> Boolean): List<T> =
    list.filter(predicate)

rotateLeft

Returns a new list which circular rotates the elements by the specified distance to the left direction. This implementation throws an exception when n is negative, though in reality a negative rotation to the left can be considered a positive rotation to the right.

// For example:
rotateLeft(listOf(1, 2, 3, 4, 5), 2) // [3, 4, 5, 1, 2]
fun <T> rotateLeft(list: List<T>, n: Int): List<T> =
    list.slice(n until list.size) + list.slice(0 until n)

rotateRight

Returns a new list which circular rotates the elements by the specified distance to the right direction. This implementation throws an exception when n is negative, though in reality a negative rotation to the right can be considered a positive rotation to the left.

// For example:
rotateRight(listOf(1, 2, 3, 4, 5), 2) // [4, 5, 1, 2, 3]
fun <T> rotateRight(list: List<T>, n: Int): List<T> =
    list.takeLast(n % list.size) + list.dropLast(n % list.size)

sample

Returns a random element from a list.

fun <T> sample(list: List<T>): T =
    list.random()

sampleSize

Gets n random elements from a list, up to the size of the list.

fun <T> sampleSize(list: List<T>, n: Int): List<T> =
    list.shuffled().take(n)

segmentLength

Computes length of longest segment within the given list whose elements all satisfy some predicate.

// For example:
segmentLength(listOf('d', 'e', 'f', 'a', 'b', 'c', 'd')) { char -> char == 'a' || char == 'b' || char == 'c' } // 3
fun <T> segmentLength(list: List<T>, predicate: (T) -> Boolean): Int =
    list.fold(0 to 0) { (longest, current), t -> if (predicate(t)) longest to current + 1 else max(longest, current) to 0 }.first

shank

Returns a new list with changes in the contents of this list, removing or replacing existing elements and/or adding new elements.

// For example:
val names = listOf("alpha", "bravo", "charlie")
shank(names, 1, 0, "delta") // [alpha, delta, bravo, charlie]
shank(names, 1, 1) // [alpha, charlie]

start - Index at which to start changing the list deleteCount - the number of list elements to remove, beginning from start elements - the elements to add to the list, beginning from start

fun <T> shank(list: List<T>, start: Int = 0, deleteCount: Int = 0, vararg elements: T): List<T> =
    list.slice(0 until start) + elements + list.drop(start + deleteCount)

shuffle

Returns a new list with the elements of this list randomly shuffled.

fun <T> shuffle(list: List<T>): List<T> =
    list.shuffled()

slideBy

Slides a non-overlapping window of a variable size over the given list.

Each window contains elements that are equal according to the given classifier function.

// For example:
slideBy(listOf(1, 2, 3, 3, 3, 4, 5)) { it } // [[1], [2], [3, 3, 3], [4], [5]]
slideBy(listOf(1, 2, 3, 10, 12, 5, 7, 20, 29)) { it / 10 } //  [[1, 2, 3], [10, 12], [5, 7], [20, 29]]
fun <T, R> slideBy(list: List<T>, classifier: (T) -> R): List<List<T>> {
    tailrec fun slideBy_(list: List<T>, acc: MutableList<List<T>>): MutableList<List<T>> =
        if (list.isEmpty())
            acc
        else
            slideBy_(list.dropWhile { classifier(it) == classifier(list.first()) },  acc.apply { add(list.takeWhile { classifier(it) == classifier(list.first()) } )} )
    return slideBy_(list, mutableListOf())
}

sortOrder

Returns 1 if the list is sorted in ascending order, -1 if it is sorted in descending order or 0 if it is not sorted. A list with all equal values is considered sorted ascending.

// For example:
isSorted(listOf(0, 1, 2, 2)) // 1
isSorted(listOf(4, 3, 2)) // -1
isSorted(listOf(4, 3, 5)) // 0
fun <T : Comparable<T>> sortOrder(list: List<T>): Int =
    with(list.sorted()) {
        when {
            this == list ->  1
            this.asReversed() == list -> -1
            else -> 0
        }
    }

span

Returns a pair where the first element is the longest prefix of elements that satisfies the given predicate, and the second element is the remainder.

fun <T> span(list: List<T>, predicate: (T) -> Boolean): Pair<List<T>, List<T>> = 
    list.takeWhile(predicate) to list.dropWhile(predicate)

splitAt

Splits the given list at the first element which satisfies the predicate.

// For example:
splitAt(listOf(1, 2, 3, 4, 5)) { it == 3 } // [[1, 2], [3, 4, 5]]
fun <T> splitAt(list: List<T>, predicate: (T) -> Boolean): Pair<List<T>, List<T>> =
    list.takeWhile { !predicate(it) } to list.dropWhile { !predicate(it) }

startsWith

Checks whether the given list starts with the given sublist.

fun <T> startsWith(list: List<T>, subList: List<T>): Boolean =
    list.take(subList.size) == subList

symmetricDifference

Returns the symmetric difference between two lists, without filtering out duplicate values.

// For example:
symmetricDifference(listOf(1, 2, 3), listOf(1, 2, 4)) // [3, 4]
symmetricDifference(listOf(1, 2, 2), listOf(1, 3, 1)) // [2, 2, 3]
fun <T> symmetricDifference(first: List<T>, second: List<T>): List<T> =
    ((first subtract second) + (second subtract first)).toList()

symmetricDifferenceBy

Returns the symmetric difference between two lists, after applying the provided function to each element of both.

// For example:
symmetricDifferenceBy(listOf(2.1, 1.2), listOf(2.3, 3.4)) { floor(it) } // [1.2, 3.4]
fun <T, R> symmetricDifferenceBy(first: List<T>, second: List<T>, function: (T) -> R): List<T> {
    val mapFirst = first.toSet().map(function)
    val mapSecond = second.toSet().map(function)
    return first.filterNot { mapSecond.contains(function(it)) } + second.filterNot { mapFirst.contains(function(it)) }
}

symmetricDifferenceWith

Returns the symmetric difference between two lists, using a provided function as a comparator.

// For example:
symmetricDifferenceWith(
  listOf(1.0, 1.2, 1.5, 3.0, 0.0),
  listOf(1.9, 3.0, 0.0, 3.9),
  { a, b -> round(a) == round(b) }
) // [1.0, 1.2, 3.9]
fun <T> symmetricDifferenceWith(first: List<T>, second: List<T>, function: (T, T) -> Boolean): List<T> =
    first.filter { a -> second.none { b -> function(a ,b) } } +
        second.filter { b -> first.none { a -> function(a, b) } }

tail

Returns all elements in a list except for the first one.

fun <T> tail(list: List<T>): List<T> =
    list.drop(1)

take

Returns the first n elements.

Use Array.prototype.slice() to create a slice of the array with n elements taken from the beginning.

fun <T> take(list: List<T>, n: Int): List<T> =
    list.take(n)

takeRight

Returns the last n elements.

fun <T> takeRight(list: List<T>, n: Int): List<T> =
    list.takeLast(n)

takeRightWhile

Returns the last n elements satisfying the given predicate.

// For example:
takeRightWhile(listOf(1, 2, 3, 4)) { it >= 3 } // [3, 4]
fun <T> takeRightWhile(list: List<T>, predicate: (T) -> Boolean): List<T> =
    list.takeLastWhile(predicate)

takeWhile

Returns the first n elements satisfying the given predicate.

// For example:
takeWhile(listOf(1, 2, 3, 4)) { it < 3 } // [1, 2]
fun <T> takeWhile(list: List<T>, predicate: (T) -> Boolean): List<T> =
    list.takeWhile(predicate)

union

Returns every element that exists in any of the two lists, removing duplicates.

// For example:
union(listOf(1, 2, 3), listOf(4, 3, 2)) // [1, 2, 3, 4]
fun <T> union(first: List<T>, second: List<T>): List<T> =
    (first union second).toList()

unionBy

Returns every element that exists in any of the two lists once, after applying the provided function to each element of both.

// For example:
unionBy(listOf(2.1), listOf(1.2, 2.3)) { floor(it) } // [2.1, 1.2]
fun <T, R> unionBy(first: List<T>, second: List<T>, function: (T) -> R): List<T> {
    val mapFirst = first.toSet().map(function)
    return (first.toSet() + second.toSet().filterNot { mapFirst.contains(function(it)) }).toList()
}

unionWith

Returns every element that exists in any of the two lists once, using a provided comparator function.

// For example:
unionWith(listOf(1.0, 1.2, 1.5, 3.0, 0.0), listOf(1.9, 3.0, 0.0, 3.9)) { a, b -> round(a) == round(b) } // [1.5, 3.0, 0.0, 3.9]
fun <T> unionWith(first: List<T>, second: List<T>, function: (T, T) -> Boolean): List<T> =
    (first.filter { a -> second.any { b -> function(a, b) } } union
            second.filter { b -> first.any { a -> function(a, b) } }).toList()

unzip

Transforms a list of pairs to a pair of lists.

fun <T, U> unzip(list: List<Pair<T, U>>): Pair<List<T>, List<U>> =
    list.unzip()

zip

Returns a list of pairs built from the elements of each list with the same index. The returned list has length of the shortest list, so the longer list has some ignored elements.

fun <T, U> zip(first: List<T>, second: List<U>): List<Pair<T, U>> =
    first.zip(second)

zipAll

Returns a list of pairs built from the elements of each list with the same index, using the default value if any list is shorter. The returned list has length of the longest list

// For example:
zipAll(listOf(1, 2, 3), 0, listOf('a', 'b', 'c', 'd', 'e'), 'z') // [[1, a], [2, b], [3, c], [0, d], [0, e]]
fun <T, U> zipAll(first: List<T>, defaultT: T, second: List<U>, defaultU: U): List<Pair<T, U>> {
    val firstIt = first.iterator()
    val secondIt = second.iterator()
    return object : Iterator<Pair<T, U>> {
        override fun hasNext(): Boolean =
            firstIt.hasNext() || secondIt.hasNext()

        override fun next(): Pair<T, U> {
            val t = if (firstIt.hasNext()) firstIt.next() else defaultT
            val u = if (secondIt.hasNext()) secondIt.next() else defaultU
            return t to u
        }
    }.asSequence().toList()
}

zipKeysValues

Zip a list of keys and a list of values into a Map. Since a Map cannot have duplicate keys, if the list of keys has any duplicates, only the last one will be kept.

fun <K, V> zipKeysValues(keys: List<K>, values: List<V>): Map<K, V> =
    keys.zip(values).toMap()

zipWith

Returns a list formed by applying the given function to elements of matching indices in both lists. The returned list has length of the shortest list, so the longer list has some ignored elements.

fun <T, U, R> zipWith(first: List<T>, second: List<U>, function: (T, U) -> R): List<R> =
    first.zip(second).map { (t, u) -> function(t, u) }

zipWithIndex

Returns a list of pairs built from the elements of the list along with its index.

fun <T> zipWithIndex(list: List<T>): List<Pair<Int, T>> =
    list.withIndex().map { it.index to it.value }

zipWithNext

Returns a list of pairs built from the elements of the list along with the element at the next index.

fun <T> zipWithNext(list: List<T>): List<Pair<T, T>> =
    list.zipWithNext()

Function

allOf

Given a list of predicates, returns a single predicate that evaluates to true if all of the predicates evaluate to true, and false otherwise.

fun <T> allOf(vararg predicates: (T) -> Boolean): (T) -> Boolean =
    { t -> predicates.all { it(t) } }

andThen

Returns a function which first applies this function to the input, and then applies the after function to the result.

// For example:
String::decapitalize andThen String::hashCode
infix fun <T, U, R> ((T) -> U).andThen(after: (U) -> R): (T) -> R = { after(this(it)) }

anyOf

Given a list of predicates, returns a single predicate that evaluates to true if any of the predicates evaluate to true, and false otherwise.

fun <T> anyOf(vararg predicates: (T) -> Boolean): (T) -> Boolean =
    { t -> predicates.any { it(t) } }

applyFirst

Applies the first argument of a curried function, returning a function taking 1 less argument.

fun <T, U, R> applyFirst(function: (T) -> (U) -> R, first: T): (U) -> R = function(first)

applySecond

Applies the second argument of a curried function, returning a function taking 1 less argument.

fun <T, U, R> applySecond(function: (T) -> (U) -> R, second: U): (T) -> R = { t -> function(t)(second) }

compose

Returns a function which first applies the before function to the input, and then applies this function to the result.

// For example:
String::hashCode compose String::decapitalize
infix fun <T, U, V> ((U) -> V).compose(before: (T) -> U): (T) -> V = { this(before(it)) }

constant

Returns a function which always evaluates to the same result, no matter the input.

fun <T, R> constant(result: R): (T) -> R = { result }

curry

Transforms a function that takes multiple arguments into one that takes a single argument - and returns another function also taking a single argument.

fun <T, U, R> ((T, U) -> R).curry(): (T) -> (U) -> R = { t -> { u -> this(t, u) } }

diverge

Tests a value against a predicate and executes either the success function or failure function.

fun <T, R> diverge(t: T, predicate: (T) -> Boolean, onSuccess: (T) -> R, onFailure: (T) -> R): R =
    if (predicate(t)) onSuccess(t) else onFailure(t)

identity

Returns a function that always returns its input argument.

fun <T> identity(): (T) -> T = { it }

isIn

Returns a predicate that tests if an object is equal to at least one of the given values.

// For example:
val is123 = isIn(1, 2, 3)
is123(1) // true
is123(4) // false
fun <T> isIn(vararg values: (T)): (T) -> Boolean =
    { t -> values.any { it == t } }

lift

Takes a function operating on raw values and lifts it to a function operating on Result values.

fun <T, U, R> lift(function: (T) -> (U) -> R): (Result<T>) -> (Result<U>) -> Result<R> =
    { resultT -> { resultU -> resultT.mapCatching(function).mapCatching { resultU.map(it) }.mapCatching { it.getOrThrow() } } }

memoize

Returns a memoized version of the given function - the function now caches all of its results.

fun <T, R> memoize(function: (T) -> R): (T) -> R =
    with(ConcurrentHashMap<T, R>()) {
        { t -> computeIfAbsent(t) { function(it) } }
    }

noneOf

Given a list of predicates, returns a single predicate that evaluates to true if none of the predicates evaluate to true, and false otherwise.

fun <T> noneOf(vararg predicates: (T) -> Boolean): (T) -> Boolean =
    { t -> !predicates.any { it(t) } }

retry

Returns a retrying version of the given function.

This implementation is based on Pierre-Yves Saumont's implementation in The Joy of Kotlin

fun <T, R> retry(times: Int, delay: Duration, function: (T) -> R): (T) -> Result<R> {
    tailrec fun retry(input: T, result: Result<R>, times: Int): () -> Result<R> {
        if (result.isSuccess || times <= 0) {
            return { result }
        } else {
            Thread.sleep(delay.toMillis())
            return retry(input, runCatching { function(input) }, times - 1)
        }
    }
    return { t -> retry(t, runCatching { function(t) }, times - 1)() }
}

sequence

Reduces many functions into a single function which produces a list.

fun <T, R> sequence(list: List<(T) -> R>): (T) -> List<R> = { t -> list.map { it(t) } }

swapArgs

Swaps the arguments of a curried function.

fun <T, U, R> ((T) -> (U) -> R).swapArgs(): (U) -> (T) -> R = { u -> { t -> this(t)(u) } }

time

Times a function and returns the time as well as the result.

fun <R> time(function: () -> R): Pair<Duration, Result<R>> {
    val start = System.nanoTime()
    val result = runCatching(function)
    val time = System.nanoTime() - start
    return Duration.ofNanos(time) to result
}

uncurry

Transforms a series of single argument functions into a single function with multiple arguments.

fun <T, U, R> ((T) -> (U) -> R).uncurry(): (T, U) -> R = { t, u -> this(t)(u) }

unlift

Takes a function operating on Result values and unlifts it to one operating on raw values.

fun <T, U, R> unlift(function: (Result<T>) -> (Result<U>) -> Result<R>): (T) -> (U) -> R =
    { t -> { u -> function(Result.success(t))(Result.success(u)).getOrThrow() } }

Lazy

asSequence

Transforms a lazy value into a lazy list, i.e. a Sequence.

fun <T> Lazy<T>.asSequence(): Sequence<T> = sequence { yield(value) }

filter

Evaluates a predicate against the value produced by the Lazy and returns a successful Result if the predicate evaluates to true, or a failure Result otherwise.

fun <T> Lazy<T>.filter(predicate: (T) -> Boolean): Lazy<Result<T>> =
    lazy { if (predicate(value)) Result.success(value) else Result.failure(IllegalArgumentException("Predicate evaluated to false.")) }

flatMap

Applies a function that produces a Lazy to the value produced by this Lazy.

fun <T, R> Lazy<T>.flatMap(function: (T) -> Lazy<R>): Lazy<R> =
    lazy { function(value).value }

forever

Returns an infinite lazy list, i.e. a Sequence, which always produces the given lazy's value.

fun <T> Lazy<T>.forever(): Sequence<T> = object : Iterator<T> {
    override fun hasNext(): Boolean = true
    override fun next(): T = value
}.asSequence()

getOrDefault

Safely gets the value produced by this Lazy and optionally returns the default value if any exception is thrown by the Lazy. The initialization of the value produced by a Lazy may throw an exception, this method guarantees that no exceptions are thrown while initializing that value.

fun <R, T : R> Lazy<T>.getOrDefault(default: R): R =
    runCatching { value }.getOrDefault(default)

lift

Takes a function operating on raw values and lifts it to a function operating on Lazy values.

fun <T, U, R> lift(function: (T) -> (U) -> R): (Lazy<T>) -> (Lazy<U>) -> Lazy<R> =
    { lazyT -> { lazyU -> lazy { function(lazyT.value)(lazyU.value) } } }

map

Applies a function to the value produced by this Lazy.

fun <T, R> Lazy<T>.map(function: (T) -> R): Lazy<R> =
    lazy { function(value) }

map2

Applies a function taking 2 raw values to 2 values produced by Lazys, and returns another Lazy.

fun <T, U, R> map2(lazy1: Lazy<T>, lazy2: Lazy<U>, function: (T) -> (U) -> R): Lazy<R> =
    lazy { function(lazy1.value)(lazy2.value) }

sequence

Reduces many Lazys into a single Lazy which produces a list.

fun <T> sequence(list: List<Lazy<T>>): Lazy<List<T>> =
    lazy { list.map { it.value } }

sequenceCatching

Reduces many Lazys into a single Lazy which produces a Result of type list. If any of the passed in Lazys throw an exception the Result will be a failure.

fun <T> sequenceCatching(list: List<Lazy<T>>): Lazy<Result<List<T>>> =
    lazy { runCatching { list.map { it.value } } }

test

Lazily tests the value produced by this Lazy against a predicate and returns a Lazy boolean.

fun <T> Lazy<T>.test(predicate: (T) -> Boolean): Lazy<Boolean> =
    lazy { predicate(value) }

Map

merge

Concatenates multiple maps into a single map, preserving the order of the passed in entries.

Note: there is expensive list concatenation in this snippet.

fun <K, V> merge(first: Map<K, V>, vararg others: Map<K, V>): Map<K, List<V>> =
    first.mapValues { entry -> listOf(entry.value) }.toMap(LinkedHashMap()).apply {
        others.forEach {
            map -> map.forEach { key, value ->  merge(key, listOf(value)) { list1, list2 -> list1 + list2 } }
        }
    }

pick

Picks the map entries which have keys contained in the given list.

fun <K, V> Map<K, V>.pick(list: List<K>): Map<K, V> =
    list.toSet().run {
        filterKeys { contains(it) }
    }

split

Splits the original map into a pair of maps, where the first map has all entries for which the predicate evaluated to true, and the second contains all other entries.

fun <K, V> Map<K, V>.split(predicate: (K) -> Boolean): Pair<Map<K, V>, Map<K, V>> =
    (HashMap<K, V>() to HashMap<K, V>()).apply {
        forEach { key, value -> if (predicate(key)) first.put(key, value) else second.put(key, value) }
    }

toEnumMap

Given a function, transforms all the values in an enum class into an EnumMap, where the key is the enum value and the value is the result of applying the function to the enum value.

enum class Stooge { MOE, LARRY, CURLY }

fun main() {
    Stooge::class.toEnumMap { it.toString().length }.forEach(::println)
}
inline fun <reified K : Enum<K>, V> KClass<K>.toEnumMap(function: (K) -> V): EnumMap<K, V> =
    enumValues<K>().fold(EnumMap(this.java)) { map, key -> map.apply { put(key, function(key)) } }

License

MIT

You might also like...
PokeDexApi is a simple version of PokeApi with search functionality.

PokeDex Api PokeDexApi is a simple version of PokeApi with search functionality based on KTOR. Documentation Base Url https://poki-dex.herokuapp.com E

Modern flashlight app with dim functionality on Android 13+
Modern flashlight app with dim functionality on Android 13+

FlashDim About this project Features Download Supported devices Screenshots Contribute Used Icons License About this project Starting with Android 13,

This is a practice app. An app that you can find random recipes and choose the ones you like.
This is a practice app. An app that you can find random recipes and choose the ones you like.

A food suggestion app like Tinder This is a practice app. In this app, you can find random recipes and choose the ones you like. This is main menu. Yo

sample project that shows you how you can use Ktor to creat a server for real Project.

Ktor-Sample This is a sample project that shows you how you can use Ktor to creat a server for real Project. What is done Save data to database (Get a

A very simple Android app which shows you random memes with the help of meme-api which you can share with your friends!
A very simple Android app which shows you random memes with the help of meme-api which you can share with your friends!

Meme Share A very simple Android app which shows you random memes with the help of meme-api which you can share with your friends! Tech stack 100% wri

Gradle plugin to manage tests which should only run nightly and not every time a CI/CD pipeline builds.

NightlyTestsPlugin Gradle Plugin to configure which (j)Unit tests should only be run nightly and not everytime a CI/CD pipeline is triggered. Usage To

An Android UI clone of ABA Mobile app for education purpose only.
An Android UI clone of ABA Mobile app for education purpose only.

ABAUIClone An Android UI clone of ABA Mobile app for education purpose only. Project Specs Language: Kotlin UI Design system: XML-based Design pattern

This is a sample app to demonstrate the power of using EventSourced models and the ease with which these can be modelled using Kotlin.
This is a sample app to demonstrate the power of using EventSourced models and the ease with which these can be modelled using Kotlin.

Lego 4 Rent This is a sample app to demonstrate the power of using EventSourced models and the ease with which these can be modelled using Kotlin. To

An Android template you can use to build your project with gradle kotlin dsl

Android Gradle KTS An Android template you can use to build your project with gradle kotlin dsl Build.gradle.kts You can use your project's build.grad

Comments
  • Question/Proposal: Use snippets inside 30 Seconds of Knowledge

    Question/Proposal: Use snippets inside 30 Seconds of Knowledge

    Hey @IvanMwiruki, I've gotten a request on my project 30SecondsOfKnowledge to add your Kotlin snippets as one more library inside the extension.

    So I'm asking for permission here. Of course I'll backlink to this repo from the Readme on my repo and also put you as one of the notable contributors. If this is okay with you please let me know so I can start working on it.

    If not, that's also cool so no pressure no sweat 😄🚀

    opened by petrovicstefanrs 4
  • Lazy<T>.asSequence returns infinite sequence

    Lazy.asSequence returns infinite sequence

    asSequence for Lazy being implemented this way

    fun <T> Lazy<T>.asSequence(): Sequence<T> = object : Iterator<T> {
            override fun hasNext(): Boolean = true
            override fun next(): T = value
        }.asSequence()
    

    returns a sequence that can be iterated only once, and once iterated it returns the value indefinitely, because hasNext is always true.

    The correct implementation would be:

    fun <T> Lazy<T>.asSequence(): Sequence<T> = sequence { yield(value) }
    
    opened by ilya-g 2
Owner
Ivan Moto
Programming is the most fun for me when it’s difficult.
Ivan Moto
Share MPS code snippets. More than just screenshots.

skadi gist Share MPS code snippets. More than just screenshots. Repository Content ide-plugin: MPS Plugin that creates a gist from the IDE written in

Skadi 6 Jan 8, 2023
Project build to understand the concepts of Git and GitHub

Project build to understand the concepts of Git and GitHub. Summarizing the concepts learnt. Created a project in Android Studio Before installing And

Rifah A Khan 0 Oct 6, 2021
Scaloid makes your Android code easy to understand and maintain.

Simpler Android Scaloid is a library that simplifies your Android code. It makes your code easy to understand and maintain by leveraging Scala languag

Sung-Ho Lee 2.1k Dec 27, 2022
Waple helps you share your Wi-Fi password quickly.💭🧇

waple Waple helps you share your Wi-Fi password quickly. ?? ?? Production intention ?? Wi-Fi passwords are usually complicated for security purposes.

Euphony 5 Jul 21, 2022
Quickly rotate screen on Android devices without second thought

Useful uitlity for ONYX BOOX Eink devices. It provides several quick actions to be added in top system panel

Daniel Kao 21 Jan 3, 2023
Restler is a beautiful and powerful Android app for quickly testing REST API anywhere and anytime.

Restler Restler has been built with simplicity and ease of use in mind. It allows you send custom HTTP/HTTPS requests and test your REST API anywhere

Tiago 10 Dec 20, 2022
A media player, currently only for Android, that allows you to play songs in background for free

Just Listen A music player currently only for android. It is using Audius public APIs to display and get the playlists/songs. Available on google play

null 68 Dec 27, 2022
Kotter - aims to be a relatively thin, declarative, Kotlin-idiomatic API that provides useful functionality for writing delightful console applications.

Kotter (a KOTlin TERminal library) aims to be a relatively thin, declarative, Kotlin-idiomatic API that provides useful functionality for writing delightful console applications.

Varabyte 348 Dec 21, 2022
A basic Kotlin implementation of Facebook's memcache lease functionality.

Liftgate Lease A basic Kotlin implementation of Facebook's memcache lease functionality. How it works If the cache key is empty or has been invalidate

null 6 Nov 10, 2022
Library to generalize functionality between several projects

libreforge libreforge is a library to generalize functionality between several projects, notably EcoArmor, EcoWeapons, and Reforges. Get from JitPack:

Auxilor 20 Dec 20, 2022