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

时间:2016-04-28 21:01:14

标签: scala cartesian-product

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

它几乎是一种“笛卡尔”产品,所以我想知道它是一个很好的解决方案(保持代码简单)来解决它。

1 个答案:

答案 0 :(得分:4)

没有这样的内置功能,但创建自己的功能很容易。为了示例,我假设Foo是简单StringverifySimilitude比较两个字符串的第一个字符。

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行为创建实现hashCodeverifySimilitude的包装类。重复使用上面的示例,它将如下所示:

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