kotlin - Kotlin distinctBy 有条件
问题描述
我有多个具有相同键的对象的数组,其他对象有空值,我希望使用 distinctBy 删除重复项并获取值具有最长字符串的对象。
data class ObjA(val key: String, val value: String)
fun test() {
val listOfA = mutableListOf(
ObjA("one", ""), //This will be taken in distinctBy.
ObjA("one", "o"),
ObjA("one", "on"),
ObjA("one", "one"), //This will be ignored in distinctBy. I WANT THIS ONE.
ObjA("two", ""), //This will be returned in distinctBy
ObjA("two", "2"),
ObjA("two", "two"), //But I want this.
ObjA("three", "3"),
ObjA("four", "4"),
ObjA("five", "five")
)
val listOfAWithNoDuplicates = listOfA.distinctBy { it.key }
for (o in listOfAWithNoDuplicates) {
println("key: ${o.key}, value: ${o.value}")
}
}
输出
key: one, value:
key: two, value:
key: three, value: 3
key: four, value: 4
key: five, value: five
如何使这项工作。任何帮助将不胜感激。
解决方案
由于distinctBy
只是根据您的选择器(并且按照列表的顺序)返回不同的键,因此您最终会得到唯一的键,但还没有您想要的值。
对于那个特定的用例,我可能只是预先排序,然后是distinctBy
listOfA.sortedByDescending { it.value.length }
.distinctBy { it.key }
它会创建一个新列表,sortedByDescending
或者您只需预先对当前列表进行排序 ( sortByDescending
) 并distinctBy
稍后应用,例如:
listOfA.sortByDescending { it.value.length }
listOfA.distinctBy { it.key }
在这两种情况下,您都会得到一个List<ObjA>
具有预期值的新值。
我还想到了其他几个变体。所有这些变体都会将结果放入Map<String, ObjA>
其中 key 实际上是 unique ObjA.key
。如果您对 key/ -mapping.values
不感兴趣,您可能想直接致电。ObjA
变体使用
groupingBy
andreduce
:listOfA.groupingBy { it.key } .reduce { _, acc, e-> maxOf(e, acc, compareBy { it.value.length }) }
使用普通
forEach
/for
并填充自己的变体Map
:val map = mutableMapOf<String, ObjA>() listOfA.forEach { map.merge(it.key, it) { t, u -> maxOf(t, u, compareBy { it.value.length }) } }
变体使用
fold
andmerge
(与之前的非常相似......只是使用fold
而不是for
/forEach
):listOfA.fold(mutableMapOf<String, ObjA>()) { acc, objA -> acc.apply { merge(objA.key, objA) { t, u -> maxOf(t, u, compareBy { it.value.length }) } } }
变体使用
groupBy
后跟mapValues
(但您实际上是在创建 1 个您立即丢弃的地图):listOfA.groupBy { it.key } // the map created at this step is discarded and all the values are remapped in the next step .mapValues { (_, values) -> values.maxBy { it.value.length }!! }