在Scala中比较两个case class实例

3

我有一个样例类,假设为Person(name:String,age:Int,address:String),同时我有一个该类实例的列表。

object HelloWorld {
   def main(args: Array[String]) {
      case class Person(name: String,age: Int,location :String)
      val per1=Person("gaurav",21,"chennai")
      val per2=Person("gaurav",21,"pune")
      
      val per3=Person("sur",26,"delhi")
      
      val lst=per1::per2::per3::Nil
}
}

如何只比较该案例类的两个字段(例如名称和年龄)的实例,并在发现任何重复项时删除重复项?

2个回答

5

如果您正在使用Scala 2.13.x,您可以使用distinctBy()函数。

List(Person("gaurav",21,"chennai")
    ,Person("gaurav",21,"pune")
    ,Person("sur",26,"delhi"))
  .distinctBy(p => (p.name,p.age))
//res0: List[Person] = List(Person(gaurav,21,chennai), Person(sur,26,delhi))

Scala 2.13.x之前版本

没有distinctBy()函数时,我可能会使用List的折叠操作来构建结果。

....foldLeft((List.empty[Person],Set.empty[(String,Int)])){
     case ((acc,seen), prsn@Person(nm,age,_)) => 
       if (seen(nm -> age)) (acc, seen)
       else (prsn::acc, seen+(nm -> age))
   }._1.reverse
//same result

谢谢。这很简洁,而且运行得非常好。你有没有想过如何在Scala 2.12或2.11的较低版本中实现它? - Gaurav Gupta

2

您可以使用一些缓存和foldLeft

val (_, distinctLst) = lst.foldLeft(Set.empty[(String, Int)] -> Vector.empty[Person]){
  case ((metPersons, persons), nextPerson) if metPersons.contains(nextPerson.name -> nextPerson.age) => metPersons -> persons
  case ((metPersons, persons), nextPerson) => (metPersons + (nextPerson.name -> nextPerson.age)) -> (persons :+ nextPerson)
}
println(distinctLst.toList) // List(Person(gaurav,21,chennai), Person(sur,26,delhi))

或者您可以覆盖 equalshashCode 方法来处理 Person,但要小心,这将改变整个程序中的 Person 行为。

case class Person(name: String, age: Int, location: String) {
  override def equals(o: Any): Boolean =
    o match {
      case Person(n, a, _) => n == name && a == age
      case _ => false
    }

  override def hashCode(): Int = (name -> age).hashCode()
}

val per1 = Person("gaurav", 21, "chennai")
val per2 = Person("gaurav", 21, "pune")
println(per1 == per1) // true
println(per1 == per2) // true

val per3 = Person("sur", 26, "delhi")
val lst = per1 :: per2 :: per3 :: Nil
println(lst.distinct) // List(Person(gaurav,21,chennai), Person(sur,26,delhi))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接