0

I've got a List[Any] that looks like:

val a: List[Any] = List(1, "a", "b", 2.0)

I also have a case class that looks like:

case class Data(field1: Int, field2: String, field3: String, field4: Double)

I'd like to instantiate a case class Data with the values from a to look like:

val d = Data(1, "a", "b", 2.0)

I know I can iterate through a, but for a large list that seems cumbersome.

RAGHHURAAMM
  • 1,099
  • 7
  • 15
jstuartmill
  • 288
  • 5
  • 11

2 Answers2

6

If you are using shapeless,

libraryDependencies += "com.chuusai" %% "shapeless" % "2.3.3"

You can apply the tuple to your case class,

scala> import shapeless._
import shapeless._

scala> import syntax.std.traversable._
import syntax.std.traversable._

scala> case class Data(field1: Int, field2: String, field3: String, field4: Double)
defined class Data

scala> val a: List[Any] = List(1, "a", "b", 2.0)
a: List[Any] = List(1, a, b, 2.0)

scala> (Data.apply _) tupled a.toHList[Int::String::String::Double::HNil].get.tupled
res1: Data = Data(1,a,b,2.0)

typesafe way to apply tuple on data class,

scala> a.toHList[Int::String::String::Double::HNil].map(_.tupled).map(t => (Data.apply _) tupled t)
res2: Option[Data] = Some(Data(1,a,b,2.0))
prayagupa
  • 30,204
  • 14
  • 155
  • 192
3

There is no way to do this in a type-safe way. Lists' lengths aren't known until runtime, so there's no way to ensure that a.length == Data#productArity (see? we're comparing a field of an instance to a field of a type).

You should think about how to not use a List to represent your data in the first place.

If you could represent your data as a tuple, you could use this answer as inspiration, but there be dragons: tuples are nearly as dubious as lists here. Try to instantiate your case class directly.

erip
  • 16,374
  • 11
  • 66
  • 121