CoolGoose
CoolGoose

Reputation: 160

Scala converting List of case class to List of another case class

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

Answers (4)

Dmytro Mitin
Dmytro Mitin

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

esse
esse

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

sarveshseri
sarveshseri

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

jwvh
jwvh

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

Related Questions