Kotlin与众不同

时间:2019-05-22 10:46:18

标签: kotlin

我有多个具有相同键的对象的数组,其他对象的值为空,我希望使用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}")
    }
}

如何进行这项工作。任何帮助将不胜感激。

2 个答案:

答案 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

  1. 使用groupingByreduce的变量:

    listOfA.groupingBy { it.key }
           .reduce { _, acc, e->
             maxOf(e, acc, compareBy { it.value.length })
           }
    
  2. 变量使用普通的forEach / for并填充其自己的Map

    val map = mutableMapOf<String, ObjA>()
    listOfA.forEach {
        map.merge(it.key, it) { t, u ->
            maxOf(t, u, compareBy { it.value.length })
        }
    }
    
  3. 使用foldmerge的变体(与以前的变体非常相似,只是使用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 })
        }
      }
    }
    
  4. 使用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)