Kotlin经常使用非常务实的方法。我想知道是否有一些我不知道的方法来简化只要求一些已知值的过滤谓词。
例如,考虑以下列表:
val list = listOf("one", "two", "2", "three")要过滤出"two"和"2"过滤,可以通过几种方式完成,例如:
list.filter {
it in listOf("two", "2") // but that creates a new list every time... (didn't check though)
}
// extracting the list first, uses more code... and may hide the list somewhere sooner or later
val toCheck = listOf("two", "2")
list.filter { it in toCheck }
// similar, but probably less readable due to naming ;-)
list.filter(toCheck::contains)
// alternative using when, but that's not easier for this specific case and definitely longer:
list.filter {
when (it) {
"two", "2" -> true
else -> false
}
}
// probably one of the simplest... but not so nice, if we need to check more then 2 values
list.filter { it == "two" || it == "2" }我想知道..。有没有像list.filter { it in ("two", "2") }这样的东西或任何其他简单的方法来为已知值/常量创建/使用短谓词?最后,这就是我想要检查的全部内容。
编辑:我刚刚意识到这个示例没有多大意义,因为listOf("anything", "some", "other").filter { it in listOf("anything") }总是:listOf("anything")。然而,列表交集在处理的星座中是有意义的,例如Map。在过滤器实际上不只返回过滤值的地方(例如.filterKeys)。然而,减法(即list.filterNot { it in listOf("two", "2") })在列表中也是有意义的。
发布于 2018-08-28 17:06:09
Kotlin在集合上提供了一些集合操作,这些集合是
intersect (两个集合在common)union中拥有的内容)(将两个collections)subtract (不包含另一个元素的集合)组合在一起)在您的示例中,您可以使用设置操作subtract而不是过滤器
val filteredList = list.subtract(setOf("two","2"))这就对了。
编辑:
有趣的(双关语)还不止于此:您可以使用自己的函数来扩展集合,比如丢失的outerJoin,或者用于过滤的函数,比如without或运算符,比如用于intersect的/
例如,通过添加这些
infix fun <T> Iterable<T>.without(other Iterable<T>) = this.subtract(other)
infix fun <T> Iterable<T>.excluding(other Iterable<T>) = this.subtract(other)
operator fun <T> Iterable<T>.div(other: Iterable<T>) = this.intersect(other)您的代码-当使用intersect应用于示例时-将变为
val filtered = list / filter //instead of intersect filter 或者-而不是减法:
val filtered = list without setOf("two", "2")或
val filtered = list excluding setOf("two", "2")够实际了吗?
发布于 2018-08-28 17:20:23
我认为没有什么比创建过滤列表/集合然后应用它更简单的了:
val toCheck = listOf("two", "2")
val filtered = list.filter { it in toCheck }或
val toCheck = setOf("two", "2")
val filtered = list.filter { it in toCheck } 但如果您愿意,也可以创建一个Predicate:
val predicate: (String) -> Boolean = { it in listOf("2", "two") }
val filtered = list.filter { predicate(it) }编辑过滤器:至于使用minus的方法,这里没有提到,但它并没有提供简单性或效率,因为它本身使用了:
/**
* Returns a list containing all elements of the original collection except the elements contained in the given [elements] collection.
*/
public operator fun <T> Iterable<T>.minus(elements: Iterable<T>): List<T> {
val other = elements.convertToSetForSetOperationWith(this)
if (other.isEmpty())
return this.toList()
return this.filterNot { it in other }
}(来自Collections.kt)
发布于 2018-08-28 18:42:14
现在,我得到了以下结论:
fun <E> containedIn(vararg elements: E) = { e:E -> e in elements }
fun <E> notContainedIn(vararg elements: E) = { e:E -> e !in elements }它可以用于使用filter的地图和列表,例如:
list.filter(containedIn("two", "2"))
list.filter(notContainedIn("two", "2"))
map.filterKeys(containedIn("two", "2"))
map.filterValues(notContainedIn("whatever"))事实上,它可以用于任何事情(如果你喜欢的话):
if (containedIn(1, 2, 3)(string.toInt())) {我的第一种方法受到Gerald Mückes的启发,但使用了minus而不是subtract (所以它只涉及减法部分):
(list - setOf("two", "2"))
.forEach ...或者使用自己的扩展函数并使用vararg
fun <T> Iterable<T>.without(vararg other: T) = this - other使用以下用法:
list.without("two", "2")
.forEach... // or whatever...然而,使用上面的变体,就不可能有中缀了。对于只有一次排除的情况,还可以提供中缀...否则,必须实现Iterable-overload:
infix fun <T> Iterable<T>.without(other : T) = this - other
infix fun <T> Iterable<T>.without(other : Iterable<T>) = this - other用法:
list without "two"
list without listOf("two", "2")https://stackoverflow.com/questions/52053755
复制相似问题