Reputation: 160
case class student1(name :String, marks :Long)
case class student2(studentName:String, marks:Long)
val mylist:List[student1] = List( student1("a",100) , student1("b",200))
How can I convert mylist
into List[student2]
in more elegant way than this?
val res: List[student2] = mylist.map(s => student2(s.name,s.marks))
Upvotes: 1
Views: 467
Reputation: 51658
@sarveshseri's (@esse's) solution seems to be the simplest one in Scala 2 (Scala 3). The following solutions using libraries are harder but more flexible.
If you have the only such transormation I'd stay with your approach or with the one suggested by @wvh.
If you have many such transformations consider to use one of data manipulating libraries.
For example Chimney
import io.scalaland.chimney.dsl._
val res: List[student2] = mylist.map(
_.into[student2]
.withFieldRenamed(_.name, _.studentName)
.transform
)
or Shapeless
import shapeless.{Generic, HList}
trait Convert[A, B] {
def apply(a: A): B
}
object Convert {
implicit def mkConvert[A <: Product, B <: Product, L <: HList](implicit
genericA: Generic.Aux[A, L],
genericB: Generic.Aux[B, L]
): Convert[A, B] = a => genericB.from(genericA.to(a))
}
implicit class ConvertOps[A](val a: A) extends AnyVal {
def to[B](implicit convert: Convert[A, B]): B = convert(a)
}
val res: List[student2] = mylist.map(_.to[student2])
Also look at Monocle or Quicklens.
Upvotes: 2
Reputation: 1551
If you are using Scala 3 (aka dotty), the following code works:
scala> import scala.deriving.Mirror
scala> mylist.map(summon[Mirror.Of[student2]].fromProduct)
val res1: List[student2] = List(student2(a,100), student2(b,200))
Upvotes: 1
Reputation: 13985
First of all, please name your classes
in CapitalCamelCase
. So Student1
and Student2
.
Now, If you have two exactly same case classes
like in this case, you can easily convert between them without using any libraries.
val myList2: List[Student2] =
mylist.map(s => Student2.tupled(Student1.unapply(s).get))
This will work for any two case classes
A
and B
which are similar in strcuture.
Upvotes: 2
Reputation: 51271
You could add an auxiliary constructor.
case class student2(studentName:String, marks:Long) {
def this(s:student1) = this(s.name, s.marks)
}
. . .
val res: List[student2] = mylist.map(new student2(_))
Or you could just do a pattern match, but for that you really should capitalize your class names.
val res: List[Student2] =
mylist.map{case Student1(n,m) => Student2(n,m)}
Upvotes: 3