Reputation: 2794
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.
Upvotes: 53
Views: 39658
Reputation: 93
You can create a triple:
myObjectList.distinctBy { Triple(it.firstField, it.secondField, it.thirdField) }
The distinctBy
will use equality of Triple
to determine uniqueness.
*I have implemented in this way, it provides most Unique list 👍
Upvotes: 0
Reputation: 13865
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, ...) }
Upvotes: 18
Reputation: 100368
You can create a pair:
myObjectList.distinctBy { Pair(it.myField, it.myOtherField) }
The distinctBy
will use equality of Pair
to determine uniqueness.
Upvotes: 97