Kotlin Filter list according to another list

I have a list of all market types, and a list of all markets (each object having a market typeId)

I want to have a market type list containing only the market types in the all markets list (without having the market types duplicated). How to do so?

Here's my code:

for (i in marketsFilter.indices) {
    val market = marketsFilter[i]
    marketTypes.add(MyApplication.allMarketTypes.single { 
        it.id == market.marketTypeId 
    })
}

Upvotes: 0

Views: 4514

Answers (3)

for (i in marketsFilter.indices) {
     val market = marketsFilter[i]
     marketTypes.add(
         MyApplication.allMarketTypes.single { it.id == market.marketTypeId })
}

marketTypes = marketTypes.distinct().toMutableList()

Upvotes: 0

Willi Mentzel
Willi Mentzel

Reputation: 29844

You can express that more concise using map:

marketsFilter.map { market ->
   MyApplication.allMarketTypes.single { it.id == market.marketTypeId }
}.distinct()

No need to handle raw indices.

Note: If you want to use single dependes on your use case, take a look the list below and decide for yourself.


single: Returns the single element matching the given predicate, or throws exception if there is no or more than one matching element.

singleOrNull: Returns the single element matching the given predicate, or null if element was not found or more than one element was found.

first: Returns the first element matching the given predicate or throws an exception if there is none.

firstOrNull: Returns the first element matching the given predicate, or null if element was not found.

If you decide to use a ...OrNull variant use mapNotNull to discard the null values.

marketsFilter.mapNotNull { market ->
    // ...
}.distinct()

Upvotes: 2

Roland
Roland

Reputation: 23262

You may be interested in the following:

val marketTypes = marketsFilter.mapNotNull { market ->
                                  MyApplication.allMarketTypes
                                                        .singleOrNull { it.id == market.marketTypeId }
                               }.distinct().toMutableList()

You may also be interested in the vice-versa approach, basically filtering just the market types for the ids of the market filter, e.g.:

val marketTypes = MyApplication.allMarketTypes.filter { type -> marketsFilter.any { it.marketTypeId == type.id } }
                                              .toMutableList() // no distinct needed

You may also want to replace any .distinct().toMutableList() with a .toMutableSet() if that also suites your needs.

Note also, if you check your allMarketTypes often, you may rather want to put them in a map, e.g.:

val allMarketTypesMap = allMarketTypes.associateBy { it.id }

That way your further mappings will become much easier, e.g.:

val marketTypes = marketsFilter.mapNotNull { allMarketTypesMap[it.marketTypeId] }
                               .distinct().toMutableList() // or just .toMutableSet()

As a side-note regarding duplicates in the allMarketTypes (in case there are any): associateBy will collect just the last of all entries with the same id, basically discarding any duplicate market type. single on the other hand will basically fail if there are more then one market type with same id or none (or if you use singleOrNull it will instead return null). Just keep that in mind.

Upvotes: 0

Related Questions