Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I remove duplicate objects with distinctBy from a list in Kotlin?

Tags:

kotlin

How can I use distinctBy on a list of custom objects to strip out the duplicates? I want to determine "uniqueness" by multiple properties of the object, but not all of them.

I was hoping something like this would work, but no luck:

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

Edit: I'm curious how to use distinctBy with any number of properties, not just two like in my example above.

like image 464
Nate Jenson Avatar asked Aug 25 '17 14:08

Nate Jenson


People also ask

How do you use Distinctby in Kotlin?

Returns a list containing only elements from the given array having distinct keys returned by the given selector function. Among elements of the given array with equal keys, only the first one will be present in the resulting list.

How do I remove duplicate characters in a string in Kotlin?

In order to remove extra whitespaces in a string, we will use the replace() function along with toRegex() function from the String class. To replace all the consecutive whitespaces with a single space " ", use the replace() function with the regular expression "\s+" which matches with one or more whitespace characters.


2 Answers

You can create a pair:

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

The distinctBy will use equality of Pair to determine uniqueness.

like image 130
nhaarman Avatar answered Oct 05 '22 15:10

nhaarman


If you look at the implementation of the distinctBy, it just adds the value you pass in the lambda to a Set. And if the Set did not already contain the specified element, it adds the respective item of the original List to the new List and that new List is being returned as the result of 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
}

So you can pass a composite object that holds the properties that you require to find the uniqueness.

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

And pass that Selector object inside the lambda:

myObjectList.distinctBy { Selector(it.property1, it.property2, ...) }
like image 14
Bob Avatar answered Oct 05 '22 15:10

Bob