Home > database >  Transform a list of object to lists of its field
Transform a list of object to lists of its field

Time:11-24

I have a List[MyObject], with MyObject containing the fields field1, field2 and field3.

I'm looking for an efficient way of doing :

Tuple3(_.map(_.field1), _.map(_.field2), _.map(_.field3))

In java I would do something like :

Field1Type f1 = new ArrayList<Field1Type>();
Field2Type f2 = new ArrayList<Field2Type>();
Field3Type f3 = new ArrayList<Field3Type>();


for(MyObject mo : myObjects) {
    f1.add(mo.getField1());
    f2.add(mo.getField2());
    f3.add(mo.getField3());
}

I would like something more functional since I'm in scala but I can't put my finger on it.

CodePudding user response:

Get 2\3 sub-groups with unzip\unzip3

Assuming the starting point:

val objects: Seq[MyObject] = ???

You can unzip to get all 3 sub-groups:

val (firsts, seconds, thirds) =  
  objects
    .unzip3((o: MyObject) => (o.f1, o.f2, o.f3))

What if I have more than 3 relevant sub-groups ?

If you really need more sub-groups you need to implement your own unzipN however instead of working with Tuple22 I would personally use an adapter:


case class MyObjectsProjection(private val objs: Seq[MyObject]) {
  
  lazy val f1s: Seq[String] =
    objs.map(_.f1)

  lazy val f2s: Seq[String] =
    objs.map(_.f2)

    ... 
  
  lazy val f22s: Seq[String] =
    objs.map(_.f3)
}

val objects: Seq[MyClass] = ???
val objsProjection = MyObjectsProjection(objects)

objs.f1s
objs.f2s
...
objs.f22s

Notes:

  • Change MyObjectsProjection according to your needs.
  • This is from a Scala 2.12\2.11 vanilla perspective.

CodePudding user response:

The following will decompose your objects into three lists:

case class MyObject[T,S,R](f1: T, f2: S, f3: R)

val myObjects: Seq[MyObject[Int, Double, String]] = ???

val (l1, l2, l3) = myObjects.foldLeft((List.empty[Int], List.empty[Double], List.empty[String]))((acc, nxt) => {
  (nxt.f1 :: acc._1, nxt.f2 :: acc._2, nxt.f3 :: acc._3)
})
  • Related