【问题标题】:How can I remove duplicate objects with distinctBy from a list in Kotlin?如何从 Kotlin 的列表中删除具有 distinctBy 的重复对象?
【发布时间】:2017-08-25 14:31:34
【问题描述】:

如何在自定义对象列表中使用distinctBy 来去除重复项?我想通过对象的多个属性来确定“唯一性”,但不是全部。

我希望这样的事情会奏效,但没有运气:

val uniqueObjects = myObjectList.distinctBy { it.myField, it.myOtherField }

编辑:我很好奇如何将distinctBy 与任意数量的属性一起使用,而不仅仅是我上面示例中的两个。

【问题讨论】:

    标签: kotlin


    【解决方案1】:

    您可以创建一对:

    myObjectList.distinctBy { Pair(it.myField, it.myOtherField) }
    

    distinctBy 将使用 Pair 的相等性来确定唯一性。

    【讨论】:

    • 或者甚至只是it.myField to it.myOtherField
    • 谢谢,但是如果我需要比较四个、五个或更多属性呢?
    • 要比较更多的值,可以使用.distinctBy { listOf(...) }
    • 还有另一种非惯用方式 - 覆盖 equalshashCode 并仅比较确定重复所需的少数字段,然后使用简单的 distinct()
    • MutableList 是否有任何“就地”想法来区分?
    【解决方案2】:

    如果您查看 distinctBy 的实现,它只是将您在 lambda 中传递的值添加到 Set。如果Set 还没有包含指定的元素,它会将原始List 的相应项添加到新的List 中,并且新的List 将作为distinctBy 的结果返回。

    public inline fun <T, K> Iterable<T>.distinctBy(selector: (T) -> K): List<T> {
        val set = HashSet<K>()
        val list = ArrayList<T>()
        for (e in this) {
            val key = selector(e)
            if (set.add(key))
                list.add(e)
        }
        return list
    }
    

    因此,您可以传递一个复合对象,其中包含查找唯一性所需的属性。

    data class Selector(val property1: String, val property2: String, ...)
    

    然后在 lambda 中传递 Selector 对象:

    myObjectList.distinctBy { Selector(it.property1, it.property2, ...) }
    

    【讨论】:

      【解决方案3】:

      你可以创建一个三元组:

      myObjectList.distinctBy { Triple(it.firstField, it.secondField, it.thirdField) }
      

      distinctBy 将使用 Triple 的相等性来确定唯一性。

      *我是这样实现的,它提供了最独特的列表?

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-07-09
        • 2019-07-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多