我有一个案例类列表,实例彼此相同或相似。我需要从“重复”中过滤掉这个列表。在Scala中,有这样的东西(伪代码):
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
它几乎是一种“笛卡尔”产品,所以我想知道它是一个很好的解决方案(保持代码简单)来解决它。
答案 0 :(得分:4)
没有这样的内置功能,但创建自己的功能很容易。为了示例,我假设Foo
是简单String
而verifySimilitude
比较两个字符串的第一个字符。
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
结果:
res0: List[String] = List(aa, bb, cc, d)
替代(更有效)的解决方案是根据您的equals
行为创建实现hashCode
和verifySimilitude
的包装类。重复使用上面的示例,它将如下所示:
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)
结果相同:
res1: List[String] = List(aa, bb, cc, d)
第二种方法更有效(O(N)与O(N 2 )相比),但它也有限的应用,因为它只有在你可以定义合理均匀{{1特别是hashCode
。