Home > Software design >  How to hand over Boolean operator as parameter in Kotlin?
How to hand over Boolean operator as parameter in Kotlin?

Time:11-10

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)]
  • Related