Reputation: 3221
I have two types FooApi
and FooModel
:
class FooApi (var aId)
class FooModel(var mId)
Is a way to simplify below function which filter FooModel
list base on FooApi
list:
fun f(fooModelList: List<FooModel>, fooApiList: List<FooApi>) : List<FooModel> {
return fooModelList.filter { fooApiList.map { it.aId }.contains ( it.mId ) }
}
Upvotes: 24
Views: 21925
Reputation: 23262
It looks ok to me. I would only change some minor things (not required though), so that it ends up something like the following:
fun List<FooModel>.f(fooApiList: List<FooApi>) = filter { m -> fooApiList.any { it.aId == m.mId } }
Some reasons why I did it this way:
FooModel
s, right? (that is the reason for the extension function narrowing the type to List<FooModel>
)any
instead; the nice benefit there also is that now both values that are compared are next to each otherStill, that's nearly the same as you did already... Just a bit less code and a rearrangement... Calling it by the way would look like:
val listA : List<FooModel> = TODO()
val listB : List<FooApi> = TODO()
val containedList = listA.f(listB)
If you require such a construct more often, maybe the following more generic solution is helpful:
fun <T, U> List<T>.intersect(uList: List<U>, filterPredicate : (T, U) -> Boolean) = filter { m -> uList.any { filterPredicate(m, it)} }
Which you can then also use like:
val containedList = listA.intersect(listB) {
a, b -> a.aId == b.mId
}
Then your f
again might even look just like:
fun List<FooModel>.f(fooApiList: List<FooApi>) = intersect(fooApiList) { a, b -> a.mId == b.aId }
Upvotes: 23
Reputation: 433
I would do something like
val apiList = listOf(FooApi(1), FooApi(2), FooApi(3))
val modelList = listOf(FooModel(1), FooModel(3))
val output = apiList.flatMap { api -> modelList.filter { api.id == it.id }}
Givin as output
[FooModel(id=1), FooModel(id=3)]
I don't know if the difference is significant...
Upvotes: 12