scala - iterate over case class data members -
i writing play2.1 application mongodb, , model object bit extensive. when updating entry in db, need compare temp object coming form what's in db, can build update query (and log changes).
i looking way generically take 2 instances , diff of them. iterating on each data member long, hard-coded , error prone (if a.firstname.equalsignorecase(b.firstname)) looking way iterate on data members , compare them horizontally (a map of name -> value do, or list can trust enumerate data members in same order every time).
any ideas?
case class customer( id: option[bsonobjectid] = some(bsonobjectid.generate), firstname: string, middlename: string, lastname: string, address: list[address], phonenumbers: list[phonenumber], email: string, creationtime: option[datetime] = some(datetime.now()), lastupdatetime: option[datetime] = some(datetime.now()) )
all 3 solutions below great, still cannot field's name, right? means can log change, not field affected...
expanding on @malte_schwerhoff's answer, potentially create recursive diff method not generated indexes of differences, mapped them new value @ index - or in case of nested product types, map of sub-product differences:
def diff(orig: product, update: product): map[int, any] = { assert(orig != null && update != null, "both products must non-null") assert(orig.getclass == update.getclass, "both products must of same class") val diffs = (ix <- 0 until orig.productarity) yield { (orig.productelement(ix), update.productelement(ix)) match { case (s1: string, s2: string) if (!s1.equalsignorecase(s2)) => some((ix -> s2)) case (s1: string, s2: string) => none case (p1: product, p2: product) if (p1 != p2) => some((ix -> diff(p1, p2))) case (x, y) if (x != y) => some((ix -> y)) case _ => none } } diffs.flatten.tomap }
expanding on use cases answer:
case class a(x: int, y: string) case class b(a: a, b: anyref, c: any) val a1 = a(4, "four") val a2 = a(4, "four") val a3 = a(4, "quatre") val a4 = a(5, "five") val b1 = b(a1, null, 6) val b2 = b(a1, null, 7) val b3 = b(a2, a2, a2) val b4 = b(a4, null, 8) println(diff(a1, a2)) // map() println(diff(a1, a3)) // map(0 -> 5) println(diff(a1, a4)) // map(0 -> 5, 1 -> five) println(diff(b1, b2)) // map(2 -> 7) println(diff(b1, b3)) // map(1 -> a(4,four), 2 -> a(4,four)) println(diff(b1, b4)) // map(0 -> map(0 -> 5, 1 -> five), 2 -> 8l
Comments
Post a Comment