否定Kotlin中的谓词(例如(String)-> Boolean)的简单方法 [英] Easy way to negate a predicate (e.g. (String) -> Boolean)) in Kotlin

查看:624
本文介绍了否定Kotlin中的谓词(例如(String)-> Boolean)的简单方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给出一个谓词(String) -> Boolean我想知道是否存在一种简单的方法来否定该谓词的结果. 只要使用列表,我就可以简单地从 filter filterNot ,但如果有的话,可以说... a filterKeys ?

Given a predicate (String) -> Boolean I wondered whether there is an easy way to negate the outcome of that predicate. As long as I use a list, I can simply switch from filter to filterNot, but what if I have, lets say... a Map and use filterKeys?

到目前为止,我使用的是:

What I used so far is:

val myPredicate : (String) -> Boolean = TODO()
val map : Map<String, String> = TODO()

map.filterKeys { !myPredicate(it) }

但是我不知道为什么Collection有一个重载的过滤功能,而Map没有.此外,我还想知道,为什么没有类似于Java的东西,即

But I wonder why there is an overloaded filter-function for Collection, but not for Map. Moreover I also wonder, why there isn't something similar to what we have in Java, i.e. Predicate.negate() and since Java 11 Predicate.not(..).

还是它存在,而我还没有找到?

Or does it exist and I just haven't found it?

推荐答案

当时我的方法是具有两个函数,一个使用not -operator,另一个是接受谓词的简单not -function .今天,我真的不能再推荐这种方法了,但是如果我不得不再次处理键或值的许多谓词否定,宁愿选择以下方法:

My approach at that time was to have two functions, one using the not-operator and the other being a simple not-function accepting a predicate. Today I can't really recommend that approach anymore, but would rather choose the following instead, if I have to deal with many predicate negations for keys or values again:

inline fun <K, V> Map<out K, V>.filterKeysNot(predicate: (K) -> Boolean) = filterKeys { !predicate(it) }
inline fun <K, V> Map<out K, V>.filterValuesNot(predicate: (V) -> Boolean) = filterValues { !predicate(it) }

那样,只需调用filterKeysNot(givenPredicate)即可使用给定谓词,类似于在集合上使用filterNot已经可以使用的谓词.

That way a given predicate can simply be used by just calling filterKeysNot(givenPredicate) similar to what was already possible with filterNot on collections.

针对当时的问题,我能够进行重构,以便可以对数据进行适当的分区,因此不再需要谓词否定.

For the problem I had at that time I was able to do a refactoring so that the data could be partitioned appropriately and therefore the predicate negation wasn't needed anymore.

如果仅在极少数情况下需要它,我宁愿坚持使用filterKeys { !predicate(it) }filterNot { (key, _) -> predicate(key) }.

If I only need it in rare occasions I would rather stick to filterKeys { !predicate(it) } or filterNot { (key, _) -> predicate(key) }.

以下变体展示了如何实现Predicates.notPredicate.negate之类的东西:

The following variants show how something like Predicates.not or Predicate.negate could be implemented:

以下内容将允许使用!运算符对谓词求反(如果应允许多个参数,则需要适当的重载):

The following will allow to use the !-operator to negate a predicate (if several parameters should be allowed an appropriate overload is required):

operator fun <T> ((T) -> Boolean).not() = { e : T -> !this(e) }

下一个允许使用not( { /* a predicate */ } ).但是,至少对于我来说,这不是很容易理解:

The next allows to use not( { /* a predicate */ } ). This however, at least for me, isn't really more readable:

inline fun <T> not(crossinline predicate: (T) -> Boolean)  = { e : T -> !predicate(e)}

用法:

val matchingHello : (String) -> Boolean = { it == "hello" }

mapOf("hello" to "world", "hi" to "everyone")
       .filterKeys(!matchingHello)
// or  .filterKeys(not(matchingHello))
// or  .filterKeys(matchingHello.not())
// or as shown above:
//     .filterKeysNot(matchingHello)
       .forEach(::println)   

这篇关于否定Kotlin中的谓词(例如(String)-> Boolean)的简单方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆