Scala函数比较案例类的字段并收集差异

时间:2019-04-23 13:47:45

标签: scala

我有2个案例类:

case class Person(fname: String, lname: String, age: Int, address: String)

case class PersonUpdate(fname: String, lname: String, age: Int)

因此PersonUpdate的主体具有Person的所有字段,我想编写有效的代码来获取Person和PersonUpdate并查找具有不同值的字段:

例如:

def findChangedFields(person: Person, personUpdate: PersonUpdate): Seq[String] = {

  var listOfChangedFields: List[String] = List.empty

  if (person.fname == personUpdate.fname)
    listOfChangedFields = listOfChangedFields :+ "fname"

  if (person.lname == personUpdate.lname)
    listOfChangedFields = listOfChangedFields :+ "lname"
  if (person.age == personUpdate.age)
    listOfChangedFields = listOfChangedFields :+ "age"

  listOfChangedFields
}

findChangedFields(per, perUpdate)

但是这很丑陋,我怎么能用scala的魔法写得这么好?

3 个答案:

答案 0 :(得分:2)

Something like this, maybe?

  val fields = Seq("fname", "lname", "age")
  val changedFields = person.productIterator
   .zip(personUpdate.productIterator) 
   .zip(fields.iterator)
   .collect { case ((a, b), name) if a != b => name }
   .toList

答案 1 :(得分:0)

类似这样的东西:

case class Person(fname: String, lname: String, age: Int, address: String)

case class PersonUpdate(fname: String, lname: String, age: Int)

def findFirstNameChanged(person: Person, personUpdate: PersonUpdate): List[String] = 
{

  if (person.fname == personUpdate.fname)  List("fname")
  else Nil
}

def findLastNameChanged(person: Person, personUpdate: PersonUpdate): List[String] = {

  if (person.lname == personUpdate.lname)  List("lname")
  else Nil
}

def findAgeNameChanged(person: Person, personUpdate: PersonUpdate): List[String] = {

  if (person.age == personUpdate.age)  List("age")
  else Nil
}

def findChangedFields(person: Person, personUpdate: PersonUpdate): Seq[String] = {

  findFirstNameChanged(person,personUpdate)::: 
findLastNameChanged(person,personUpdate) ::: findAgeNameChanged(person,personUpdate)
}

val per = Person("Pedro","Luis",22,"street")
val personUpdate = PersonUpdate("Pedro", "Luis",27)

findChangedFields(per, personUpdate)

答案 2 :(得分:0)

我认为您的问题类似于比较两个Set元组。请放心,两个纠正我。

这是我的解决方案,该解决方案适用于具有任意顺序字段名称的任何两个案例类

def caseClassToSet[T](inp: T)(implicit ct: ClassTag[T]): Set[(String, AnyRef)] = {
ct.runtimeClass.getDeclaredFields.map(f => {
  f.setAccessible(true)
  val res = (f.getName, f.get(inp))
  f.setAccessible(false)
  res
}).toSet
}

val person = Person("x", "y", 10, "xy")
val personUpdate = PersonUpdate("z","y",12)
val personParams: Set[(String, AnyRef)] = caseClassToSet(person)
val personUpdateParams: Set[(String, AnyRef)] = caseClassToSet(personUpdate)

println(personUpdateParams diff personParams)

Get field names list from case class获得帮助