如何从 Scala 中的 类 列表中提取唯一元素

How to extract unique elements from a list of classes in Scala

我有一个案例列表 类,这些实例彼此相同或相似。我需要从 "duplicates" 中过滤掉这个列表。在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

?

它几乎是一个 "cartesian" 产品,所以我想知道它可能是一个很好的解决方案(保持代码简单)来解决它。

没有这样的内置函数,但创建您自己的函数很容易。为了这个例子,我假设 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)

替代(更有效)的解决方案是根据您的 verifySimilitude 行为创建实现 equalshashCode 的包装器 class。重用上面的例子,这看起来像:

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(N2) 相比),但它的应用也有限,因为它只有在您可以定义时才有意义对于特定的 verifySimilitude.

相当统一 hashCode