I have a function which has quite a lot lines. In that function I have a .filter{}
like:
fun getMyListForFoo(): List<Blub> {
//.. lot of lines
return myRepo.queryList()
.filter{ it.flag == Query.IS_FOO }
.map{
//..mappings
}
}
and then I have a second function just to retrieve queries which are NOT Foo
:
fun getMyListForNotFoo(): List<Blub> {
//.. lot of lines
return myRepo.queryList()
.filter{ it.flag != Query.IS_FOO }
.map{
//..mappings
}
}
As you can the only difference is the ==
or !=
operator in the .filter
function. Although I have all the previous lines duplicated..
I bet there is a nice Kotlin way to enhance this code?
CodePudding user response:
Pass a predicate as a parameter to your function for filtering the list.
fun getMyList(predicate: (YourType) -> Boolean): List<Blub> {
//.. lot of lines
return myRepo.queryList()
.filter(predicate)
.map{
//..mappings
}
}
Usage:
val listForFoo = getMyList { it.flag == Query.IS_FOO }
val listForNotFoo = getMyList { it.flag != Query.IS_FOO }
OR, if you just want to pass a Boolean, you can also do that:
fun getMyList(filterFoo: Boolean): List<Blub> {
//.. lot of lines
return myRepo.queryList()
.filter {
val isFoo = it.flag == Query.IS_FOO
if(filterFoo) isFoo else !isFoo
}
.map{
//..mappings
}
}
CodePudding user response:
I would use partition
directly.
I created a sample in kotlinlang.org's playground and it looks like this:
// Given a "thing"
data class Thing(val id: Int, val isFoo: Boolean)
// Have a function that simplifies this:
fun filterThings(source: List<Thing>) = source.partition { it.isFoo }
// Alternatively, you could have a more generic one:
fun filterThings(source: List<Thing>,
predicate: ((Thing) -> Boolean)) = source.partition(predicate)
// And you can use either like so:
// Given the source
val source = listOf(Thing(1, true),
Thing(2, true),
Thing(3, false),
Thing(4, true),
Thing(5, false),
Thing(6, false))
// Filter them with the non-configurable version:
val results = filterThings(source)
// or the more configurable one where *you* supply the predicate:
val results = filterThings(source) { it.isFoo }
The results are going to be:
results.first
is going to be the one that pass the predicate, and the rest will be in results.second
:
results.first = [Thing(id=1, isFoo=true), Thing(id=2, isFoo=true), Thing(id=4, isFoo=true)]
results.second = [Thing(id=3, isFoo=false), Thing(id=5, isFoo=false), Thing(id=6, isFoo=false)]