Tengo una función que tiene bastantes líneas. En esa función tengo un .filter{} como:
fun getMyListForFoo(): List<Blub> { //.. lot of lines return myRepo.queryList() .filter{ it.flag == Query.IS_FOO } .map{ //..mappings } } y luego tengo una segunda función solo para recuperar consultas que NO son Foo :
fun getMyListForNotFoo(): List<Blub> { //.. lot of lines return myRepo.queryList() .filter{ it.flag != Query.IS_FOO } .map{ //..mappings } } Como puede ver, la única diferencia es el operador == o != en la función .filter . Aunque tengo todas las lineas anteriores duplicadas..
Apuesto a que hay una buena forma de Kotlin para mejorar este código.
Pase un predicado como parámetro a su función para filtrar la lista.
fun getMyList(predicate: (YourType) -> Boolean): List<Blub> { //.. lot of lines return myRepo.queryList() .filter(predicate) .map{ //..mappings } }Uso:
val listForFoo = getMyList { it.flag == Query.IS_FOO } val listForNotFoo = getMyList { it.flag != Query.IS_FOO }O, si solo desea pasar un valor booleano, también puede hacerlo:
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 } }Yo usaría la partition directamente.
Creé una muestra en el área de juegos de kotlinlang.org y se ve así:
// 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 }Los resultados van a ser:
results.first será el que pase el predicado, y el resto estará en 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)]