我有多个具有相同键的对象的数组,其他对象的值为空,我希望使用distinctBy删除重复项并获取值最长的对象。
name.widget.attrs.update({'class': 'special'})
输出
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}")
}
}
如何进行这项工作。任何帮助将不胜感激。
答案 0 :(得分:1)
distinctBy
仅根据选择器(并按照列表的顺序)返回不同的键,所以最终得到的是唯一键,但还没有所需的值。
对于该特定用例,我可能只是预先sort,然后是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>
中,其中键实际上是唯一的ObjA.key
。如果您对键/ .values
映射不感兴趣,则可能需要直接致电ObjA
。
使用groupingBy
和reduce
的变量:
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
和merge
的变体(与以前的变体非常相似,只是使用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 }!!
}
答案 1 :(得分:0)
您可以像这样使用maxBy{}
:
val x = listOfAWithNoDuplicates.maxBy { it.key.length }
println(x)
输出
ObjA(key=three, value=3)