Home > Back-end >  How to filter in kotlin using predicates
How to filter in kotlin using predicates

Time:07-07

What i'm trying to achieve is using a filter function with dynamic predicates. What I did so far is creating a function that choose the best predicate:

fun buildDatePredicate(dateFrom: LocalDate?, dateTo: LocalDate?): Predicate<MyClass> {
    if (dateFrom != null && dateTo == null) {
        return Predicate { myItem -> myItem.date.isAfter(dateFrom) }
    }
    if (dateTo != null && dateFrom == null) {
        return Predicate { myItem -> myItem.date.isBefore(dateTo) }
    }
    if (dateTo != null && dateFrom != null) {
        return Predicate { myItem ->
            myItem.date.isBefore(dateTo) && myItem.date.isAfter(dateFrom)
        }
    }

    return Predicate { true }
}

And then I tried to use filter on my list using that Predicate

myList.filter { buildDatePredicate(fromDate.toLocalDate(),toDate.toLocalDate()) }

But it does not works due to

Type mismatch.
Required:
Boolean
Found:
Predicate<MyClass>

Is it possible to achieve what i'm trying to do?

Thanks

CodePudding user response:

A simple solution is to just call the test-method on the predicate:

myList.filter { 
    val pred = buildDatePredicate(fromDate.toLocalDate(), toDate.toLocalDate())
    pred.test(it)
}

But a more idiomatic solution in Kotlin is to not use java.util.function.Predicate, but rather a function of type (MyClass) -> Boolean. Then you can just pass the result of buildDatePredicate directly to the filter function. Like this:

fun buildDatePredicate(dateFrom: LocalDate?, dateTo: LocalDate?): (MyClass) -> Boolean {
    if (dateFrom != null && dateTo == null) {
        return { myItem -> myItem.date.isAfter(dateFrom) }
    }
    if (dateTo != null && dateFrom == null) {
        return { myItem -> myItem.date.isBefore(dateTo) }
    }
    if (dateTo != null && dateFrom != null) {
        return { myItem ->
            myItem.date.isBefore(dateTo) && myItem.date.isAfter(dateFrom)
        }
    }

    return { true }
}

And then call it with:

myList.filter(buildDatePredicate(fromDate.toLocalDate(), toDate.toLocalDate()))
  • Related