如何从 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
行为创建实现 equals
和 hashCode
的包装器 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
我有一个案例列表 类,这些实例彼此相同或相似。我需要从 "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
行为创建实现 equals
和 hashCode
的包装器 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