score:2
That would be a very easy task to achieve if it would be an easy way to convert case class to map. Unfortunately, case classes don't offer that functionality out-of-box yet in Scala 2.12 (as Mario have mentioned it will be easy to achieve in Scala 2.13).
There's a library called shapeless, that offers some generic programming utilities. For example, we could write an extension function toMap
using Record
and ToMap
from shapeless:
object Mappable {
implicit class RichCaseClass[X](val x: X) extends AnyVal {
import shapeless._
import ops.record._
def toMap[L <: HList](
implicit gen: LabelledGeneric.Aux[X, L],
toMap: ToMap[L]
): Map[String, Any] =
toMap(gen.to(x)).map{
case (k: Symbol, v) => k.name -> v
}
}
}
Then we could use it for findDiff
:
def findDiff(profile: Profile): Seq[String] = {
import Mappable._
profile match {
case Profile(_, _, bankInfo, Some(userUpdatedFields)) =>
val bankInfoMap = bankInfo.toMap
userUpdatedFields.toMap.toList.flatMap{
case (k, v) if bankInfoMap.get(k).exists(_ != v) => Some(k)
case _ => None
}
case _ => Seq()
}
}
score:3
Each case class extends Product interface so we could use it to convert case classes into sets of (field, value) elements. Then we can use set operations to find the difference. For example,
def findDiff(profile: Profile): Seq[String] = {
val userUpdatedFields = profile.userUpdatedFields.get
val bankInfoData = profile.bankInfoData
val updatedFieldsMap = userUpdatedFields.productElementNames.zip(userUpdatedFields.productIterator).toMap
val bankInfoDataMap = bankInfoData.productElementNames.zip(bankInfoData.productIterator).toMap
val bankInfoDataSubsetMap = bankInfoDataMap.view.filterKeys(userUpdatedFieldsMap.keys.toList.contains)
(bankInfoDataSubsetMap.toSet diff updatedFieldsMap.toSet).toList.map { case (field, value) => field }
}
Now findDiff(profile)
should output List(phoneNumber, contactPerson)
. Note we are using productElementNames from Scala 2.13 to get the filed names which we then zip with corresponding values
userUpdatedFields.productElementNames.zip(userUpdatedFields.productIterator)
Also we rely on filterKeys and diff.
score:3
A simple improvement would be to introduce a trait
trait Fields {
val contactPerson: String
val phoneNumber: Int
val accountType: AccountType
def findDiff(that: Fields): Seq[String] = Seq(
Some(contactPerson).filter(_ != that.contactPerson).map(_ => "contactPerson"),
Some(phoneNumber).filter(_ != that.phoneNumber).map(_ => "phoneNumber"),
Some(accountType).filter(_ != that.accountType).map(_ => "accountType")
).flatten
}
case class BankInfoData(accountNumber: Int,
bankAddress: String,
bankNumber: Int,
contactPerson: String,
phoneNumber: Int,
accountType: String) extends Fields
case class UserUpdatedFields(contactPerson: String,
phoneNumber: Int,
accountType: AccountType) extends Fields
so it was possible to call
BankInfoData(...). findDiff(UserUpdatedFields(...))
If you want to further-improve and avoid naming all the fields multiple times, for example shapeless could be used to do it compile time. Not exactly the same but something like this to get started. Or use reflection to do it runtime like this answer.
Source: stackoverflow.com
Related Query
- compare case class fields with sub fields of another case class in scala
- Shapeless - turn a case class into another with fields in different order
- Scala case class copy constructor with dynamic fields
- Scala - case class with 100 fields (StackOverflowError)
- Scala compare case class and get changed fields
- scala function to compare fields of case class and collect the diff
- How to get Scala case class fields and values as (String, String) with Shapeless or Macro
- Automatic type class derivation for case classes with Scala Enumeration fields
- Change fields of case class based on map entries with simple type check in scala macros
- scala call constructor of case class with all fields except one automatically
- Parse json array to a case class in scala using playframework with the fields in json not matching the fields in case class
- How to flatten a case class with a list value to another case class properly with scala
- Converting one case class to another that is similar with additional parameter in Scala
- Using Spark converting nested json with optional fields to Scala case class not working
- Compare a list values with case class using Scala and Spark
- How to update a mongo record using Rogue with MongoCaseClassField when case class contains a scala Enumeration
- Scala case class extending Product with Serializable
- Case Classes with optional fields in Scala
- Scala case having 22 fields but having issue with play-json in scala 2.11.5
- Read CSV in Scala into case class instances with error handling
- Obtaining the full info about fields of the case class in Scala
- Scala copy case class with generic type
- Scala wont pattern match with java.lang.String and Case Class
- Custom Json Writes with combinators - not all the fields of the case class are needed
- Derived Scala case class with same member variables as base
- Scala spark: how to use dataset for a case class with the schema has snake_case?
- Replacing case class inheritance with extractors preserving exhaustiveness checks in Scala
- Play json merge formats for case class with more than 22 fields
- Problem with bounded type parameterised case class and default args in Scala
- How do I add a no-arg constructor to a Scala case class with a macro annotation?
More Query from same tag
- Serializing a tree in Play for Scala
- check data size spark dataframes
- Scala swing repaint
- Scala child class inherits parent class traits?
- SBT cannot find a package on JCenter
- InvalidActorNameException - actor name {name} is not unique
- Find several groups of ocurrences in String with regex Scala
- Unescaped messages in Play 2.0
- Strange behavior of Void and intersection types
- How to share logic between cases in pattern matching
- Scala search and replace using replace not giving expected results
- Memory leak in Scala and processes
- Can not download dependencies for SBT (the build tool for Scala) in the first run
- Implement find and remove in Scala
- From Java call Scala's Singleton object apply with trait
- What's the point of dependency injection if you still have to pass in an argument?
- Can't Import Plugin
- How to optimize this simple function in scala
- Scala java.lang.NoClassDefFoundError: org/postgresql/Driver
- how to store hashmap in cassandra table
- Spark running Liblinear unable to load JBLAS jar
- When is an empty HList not an HList?
- Meaning of -= and += in Scala Trait definition
- How to use reduce or fold to encrypt a list of string tokens?
- Mockito - Not able to Mock ResultSet
- Play 2 Anorm and scala pattern matching
- Creating and using Spark-Hive UDF for Date
- elegantly return a Map
- Refined and existential types for runtime values
- How to use quasiquotes with previously defined object