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 ) }
}
One of the utility method filter() helps to filter the stream elements that satisfy the provided criteria. The predicate is a functional interface that takes a single element as an argument and evaluates it against a specified condition.
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().
If you want to use element positions in the filter, use filterIndexed() . It takes a predicate with two arguments: the index and the value of an element. To filter collections by negative conditions, use filterNot() . It returns a list of elements for which the predicate yields false .
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 }
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...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With