6 minutes read

When we are working with collections, filtering a collection by certain criteria or checking if the collection contains elements with certain properties or predicates is a daily task in software development. To solve this task, we can use functional APIs implemented in Kotlin.

In this topic, we will present techniques to filter a collection using predicates and obtain a new collection with the elements that satisfy the given predicate .

Filtering

Kotlin offers an API that makes use of extension functions and allows you to filter the elements of a collection based on predicates. The filter() function takes a predicate and returns a new collection with the elements that satisfy the predicate (or condition). Also, we can use filterIndexed(), which takes the index of an element and the element itself and returns a collection that matches the predicate evaluated on the element. Yet another function, filterNot(), obtains a collection with the elements that do not match the predicate. These methods are available in all basic Kotlin collections (lists, sets, and maps).

val isEven: (Int) -> Boolean = { x -> x % 2 == 0 }

fun main() {
    val numbers = listOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)


    // List of even numbers
    println(numbers.filter { x -> x % 2 == 0 }) // [0, 2, 4, 6, 8, 10]
    println(numbers.filter { isEven(it) }) // [0, 2, 4, 6, 8, 10]
    println(numbers.filter(isEven)) // [0, 2, 4, 6, 8, 10]

    // List of odd numbers
    println(numbers.filter { x -> x % 2 != 0 }) // [1, 3, 5, 7, 9]
    
    // List of odd number using filterNot
    println(numbers.filterNot { x -> x % 2 == 0 }) // [1, 3, 5, 7, 9]
   
    // List even number with index greater than 3
    println(numbers.filterIndexed { i, number -> i > 3 && number % 2 == 0 }) // [4, 6, 8, 10]

    // List of words with odd index and starting with "k"
    val words = listOf("peter", "kyle", "robert", "kate", "kevin", "anne", "jeremy")
    println(words.filterIndexed { i, word -> i % 2 != 0 && word.startsWith("k") }) // [kyle, kate]
}

The functional programming filter function is an effective way to use for and if in imperative programming:

fun main() {
    val numbers = listOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
    
    val even = numbers.filter { x -> x % 2 == 0 }

    val odd = mutableListOf<Int>()
    for (i in numbers) {
        if (i % 2 != 0) {
            odd.add(i)
        }
    }

    println(even) // [0, 2, 4, 6, 8, 10]
    println(odd) // [1, 3, 5, 7, 9]
}

Filtering and types

We also have functions that offer the opportunity of filtering by the types of elements within a collection. filterIsInstance() returns a collection with the elements of the type indicated in the predicate. filterNotNull() returns all elements that are not null.

fun main() {
    val elements = listOf(null, 0, "string", 3.14, null, 'c', "Luke")

    // Only string elements
    println(elements.filter { x -> x is String }) // [string, Luke]
    println(elements.filterIsInstance<String>()) // [string, Luke]
    // not null elements
    println(elements.filterNot { x -> x == null }) // [0, string, 3.14, c, Luke]
    println(elements.filterNotNull()) // [0, string, 3.14, c, Luke]
    // only integer elements
    println(elements.filterIsInstance<Int>()) // [0]
}

Partitioning

The partition() function splits the original collection in two: one with the elements that satisfy the predicate and the other with the rest of the elements of the original collection (those that don't match the predicate).

fun main() {
    val numbers = listOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

    val (even, odd) = numbers.partition { x -> x % 2 == 0 }
    println(even) // [0, 2, 4, 6, 8, 10]
    println(odd) // [1, 3, 5, 7, 9]
}

Conclusion

In this topic, we have seen different ways to filter the elements of a collection based on a condition, which is called the predicate.

We have introduced several special functions to filter by predicates, like filter(), filterIndexed(), filterNot(), filterIsInstance(), filterNotNull(), and partition(). They offer us an elegant and efficient way of filtering collection elements.

Now is the time to check what you have learned about filtering. Let's go for it!

84 learners liked this piece of theory. 0 didn't like it. What about you?
Report a typo