Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin optimize take first n elements with filter

Tags:

kotlin

I have some list: List <Pet> I need to take 3 elements from it that satisfy the condition:

I do it like this:

list.filter { g -> !mainList.contains(g) }.take(3)

How can you optimize this code so that the filter operation is executed no more than enough times for the result?

like image 908
KosWarm Avatar asked Dec 10 '20 10:12

KosWarm


People also ask

How do you get the first N elements of a list in Kotlin?

The Take function returns a list containing the first n elements. For example, you have a list of integers starting from 1000 to 10000. Suppose you want the first 15 values from that list. Then, you can use the standard library function take that returns the first specified n elements from the list.

How do I filter data with Kotlin?

If we want to filter using element index or position, we have to use filterIndexed(). filterIndexed() function takes a predicate with two arguments: index and the value of an element. We can filter the collections by negative conditions by using filterNot().

How do you access the ArrayList elements in Kotlin?

Kotlin arrayListOf() Example 4 - get()The get() function of arrayListOf() is used to retrieve the element present at specified index. For example: fun main(args: Array<String>){ val list: ArrayList<String> = arrayListOf<String>()

How do I use a list on Kotlin?

Android Dependency Injection using Dagger with Kotlin Kotlin list is an ordered collection of items. A Kotlin list can be either mutable (mutableListOf) or read-only (listOf). The elements of list can be accessed using indices. Kotlin mutable or immutable lists can have duplicate elements.


Video Answer


1 Answers

Use a sequence. Instead of fully processing each step in turn (i.e. create a new filtered list, then take 3 elements from that) each element passes through the chain, one at a time. So you don't create intermediate lists, and you can stop as soon as you get to the element that meets your terminating condition

list.asSequence()
    .filter { g -> !mainList.contains(g) }
    .take(3)
    .toList()

Note you have to execute the sequence (with toList in this case) to turn it into a concrete collection.

Also, as the link says, creating a sequence does introduce a bunch of overhead, so it's not necessarily more efficient - you'll see benefits with bigger collections, more steps in the chain, slower computation in things like the filter functions... anything where it makes sense to really minimise memory use or exiting early makes a big difference. You should benchmark it, make sure it's the right thing to do!

Also as a bonus, your filter operation could be filterNot(mainList::contains) if you like!

like image 131
cactustictacs Avatar answered Oct 17 '22 06:10

cactustictacs