Scala 将案例列表 class 转换为另一个案例列表 class

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))

如何以比这更优雅的方式将 mylist 转换为 List[student2]

val res: List[student2] = mylist.map(s => student2(s.name,s.marks))

您可以添加辅助构造函数。

case class student2(studentName:String, marks:Long) {
  def this(s:student1) = this(s.name, s.marks)
}

. . .

val res: List[student2] = mylist.map(new student2(_))

或者您可以只进行模式匹配,但为此您确实应该将 class 名称大写。

val res: List[Student2] =
  mylist.map{case Student1(n,m) => Student2(n,m)}

() 解决方案似乎是 Scala 2 (Scala 3) 中最简单的解决方案。以下使用库的解决方案更难但更灵活。


如果你有唯一的这样的转换,我会坚持你的方法或 @wvh 所建议的方法。

如果您有许多此类转换,请考虑使用其中一个数据处理库。

例如Chimney

import io.scalaland.chimney.dsl._

val res: List[student2] = mylist.map(
  _.into[student2]
   .withFieldRenamed(_.name, _.studentName)
   .transform
)

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])

另请参阅Monocle or Quicklens

首先,请在CapitalCamelCase中命名您的classes。所以 Student1Student2.

现在,如果您有两个完全相同的 case classes,就像在这种情况下,您可以在不使用任何库的情况下轻松地在它们之间进行转换。

val myList2: List[Student2] = 
  mylist.map(s => Student2.tupled(Student1.unapply(s).get))

这将适用于结构相似的任何两个 case classes AB

如果您使用的是 Scala 3(又名 dotty),则以下代码有效:

scala> import scala.deriving.Mirror
                                                                                                                                                                           
scala> mylist.map(summon[Mirror.Of[student2]].fromProduct)
val res1: List[student2] = List(student2(a,100), student2(b,200))