Reputation: 9103
I have a list of case classes and the instances are the same or similar each other. I need to filter out this list from the "duplicates". In Scala, is there anything like this (pseudo code):
myList.unique ((obj1,obj2) => verifySimilitude(obj1,obj2))
def verifySimilitude(obj1:Foo, obj2:Foo):Boolean = // some logic to verify that objects are the same or at least similar
?
It is pretty much a "cartesian" product so I am wondering what it could be a good solution (keeping the code simple) to solve it.
Upvotes: 2
Views: 241
Reputation: 10882
There is no such built-in function, but it's easy to create your own. For the sake of the example, I'm assuming Foo
is simple String
and verifySimilitude
compares first characters of two strings.
type Foo = String
def verifySimilitude(obj1: Foo, obj2: Foo): Boolean = obj1.headOption == obj2.headOption
val myList = List("aa", "bb", "cc", "a", "b", "c", "d")
myList.foldLeft(List[String]()) {
case (accum, el) => if (accum.exists(verifySimilitude(el, _))) accum else el :: accum
}.reverse
Result:
res0: List[String] = List(aa, bb, cc, d)
Alternative (more efficient) solution would be to create wrapper class that implements equals
and hashCode
according to your verifySimilitude
behavior. Reusing the example above, this will look like:
class SimWrapper(val v:String) {
override def equals(other: Any): Boolean = other match {
case that: SimWrapper => that.v.headOption == v.headOption
case _ => false
}
override def hashCode(): Int = v.headOption.hashCode()
}
myList.map(new SimWrapper(_)).distinct.map(_.v)
With the same result:
res1: List[String] = List(aa, bb, cc, d)
Second approach is more efficient (O(N) comparing to O(N2)), but it also has limited applications, as it makes sense only when you can define reasonably uniform hashCode
for particular verifySimilitude
.
Upvotes: 4