the following code succeeds, there better way of doing same thing? perhaps specific case classes? in following code, each field of type string in simple case class, code goes through list of instances of case class , finds length of longest string of field.
case class crmcontractorrow( id: long, bankcharges: string, overtime: string, name$id: long, mgmtfee: string, contractdetails$id: long, email: string, copyofvisa: string) object go { def main(args: array[string]) { val = crmcontractorrow(1,"1","1",4444,"1",1,"1","1") val b = crmcontractorrow(22,"22","22",22,"55555",22,"nine long","22") val c = crmcontractorrow(333,"333","333",333,"333",333,"333","333") val rows = list(a,b,c) c.getclass.getdeclaredfields.filter(p => p.gettype == classof[string]).foreach{f => f.setaccessible(true) println(f.getname + ": " + rows.map(row => f.get(row).asinstanceof[string]).maxby(_.length)) } } }
result:
bankcharges: 3 overtime: 3 mgmtfee: 5 email: 9 copyofvisa: 3
if want kind of thing shapeless, i'd suggest defining custom type class handles complicated part , allows keep stuff separate rest of logic.
in case sounds tricky part of you're trying getting mapping field names string lengths of string
members of case class. here's type class that:
import shapeless._, shapeless.labelled.fieldtype trait stringfieldlengths[a] { def apply(a: a): map[string, int] } object stringfieldlengths extends lowprioritystringfieldlengths { implicit val hnilinstance: stringfieldlengths[hnil] = new stringfieldlengths[hnil] { def apply(a: hnil): map[string, int] = map.empty } implicit def caseclassinstance[a, r <: hlist](implicit gen: labelledgeneric.aux[a, r], sfl: stringfieldlengths[r] ): stringfieldlengths[a] = new stringfieldlengths[a] { def apply(a: a): map[string, int] = sfl(gen.to(a)) } implicit def hconsstringinstance[k <: symbol, t <: hlist](implicit sfl: stringfieldlengths[t], key: witness.aux[k] ): stringfieldlengths[fieldtype[k, string] :: t] = new stringfieldlengths[fieldtype[k, string] :: t] { def apply(a: fieldtype[k, string] :: t): map[string, int] = sfl(a.tail).updated(key.value.name, a.head.length) } } sealed class lowprioritystringfieldlengths { implicit def hconsinstance[k, v, t <: hlist](implicit sfl: stringfieldlengths[t] ): stringfieldlengths[fieldtype[k, v] :: t] = new stringfieldlengths[fieldtype[k, v] :: t] { def apply(a: fieldtype[k, v] :: t): map[string, int] = sfl(a.tail) } }
this looks complex, once start working shapeless bit learn write kind of thing in sleep.
now can write logic of operation in relatively straightforward way:
def maxstringlengths[a: stringfieldlengths](as: list[a]): map[string, int] = as.map(implicitly[stringfieldlengths[a]].apply).foldleft( map.empty[string, int] ) { case (x, y) => x.foldleft(y) { case (acc, (k, v)) => acc.updated(k, acc.get(k).fold(v)(accv => math.max(accv, v))) } }
and (given rows
defined in question):
scala> maxstringlengths(rows).foreach(println) (bankcharges,3) (overtime,3) (mgmtfee,5) (email,9) (copyofvisa,3)
this work absolutely case class.
if one-off thing, might use runtime reflection, or use poly1
approach in giovanni caporaletti's answer—it's less generic , mixes different parts of solution in way don't prefer, should work fine. if you're doing lot of, though, i'd suggest approach i've given here.
Comments
Post a Comment