-3

So I have a list so:

    var data = List(
      List(Some(313.062468), Some(27.847252), Some(29.847252)),
      List(Some(301.873641), Some(42.884065), Some(89.847252)),
      List(Some(332.373186), Some(53.509768), Some(10.847252))
    )

How can I compute basic function like:

For each element of each list:

First row

Some(301.873641) - Some(313.062468) / Some(313.062468)
Some(332.373186) - Some(301.873641) / Some(301.873641)

Second Column

Some(42.884065) - Some(27.847252) / Some(27.847252)
Some(53.509768) - Some(42.884065) / Some(42.884065)

Third Column

Some(89.847252) - Some(29.847252) / Some(29.847252)
Some(10.847252) - Some(89.847252) / Some(89.847252)

Im currently stuck here

data.map(_.head).foreach {
  case i => println(i)
}

This only prints the head of each nested list. I don't know how to get each element of the nested element and do the above calculation.

Result should be like this:

List(
  List(Some(-0.03573991820699504), Some(0.5399747522663995), Some(88.847252) )
  List(Some(0.10103414428290529), Some(0.24777742035415723), Some(9.847252) )
)
The Archetypal Paul
  • 41,321
  • 20
  • 104
  • 134
S. Nas
  • 331
  • 1
  • 4
  • 14
  • 4
    So this is the third very basic question you've asked around this. You're not supposed to use SO as a bot to write your code. Have you considered going off and studying Scala for a bit? There are many fine tutorials available. – The Archetypal Paul Nov 18 '16 at 13:51
  • Apologies @TheArchetypalPaul Will not happen again. I'm fairly new to Scala and would really appreciated some help – S. Nas Nov 18 '16 at 13:52
  • 3
    Seriously, you'd gain a lot more from working through this yourself and when you're really stuck, asking a specific question. – The Archetypal Paul Nov 18 '16 at 13:53
  • Apologies @TheArchetypalPaul – S. Nas Nov 18 '16 at 13:54

4 Answers4

2

Transpose the list, then use .sliding(2) to get a rolling windows of the elements:

scala> def diffPercent(o1: Option[Double], o2: Option[Double]) = (o1, o2) match {
         case (Some(d1), Some(d2)) => Some((d2 - d1) / d1)  // need to handle d1 == 0 too
         case _ => None
       }
diffPercent: (o1: Option[Double], o2: Option[Double])Option[Double]

// sample value before the final operation
scala> data.transpose.map(_.sliding(2).toList) // .toList to show the values in REPL
res13: List[List[List[Some[Double]]]] = List(List(List(Some(313.062468), Some(301.873641)), List(Some(301.873641), Some(332.373186))), ...)

scala> data.transpose.map(_.sliding(2).map {
         case o1 :: o2 :: Nil => diffPercent(o1, o2)
         case _ => None // source has less than 2 elems
       }.toList).transpose  // transpose back the list
res17: List[List[Option[Double]]] = List(List(Some(-0.03573991820699504), Some(0.5399747522663995), Some(2.010235314125401)), List(Some(0.10103414428290529), Some(0.24777742035415723), Some(-0.8792700749489812)))
Marth
  • 23,920
  • 3
  • 60
  • 72
2

This one's a bit simpler than the others, and doesn't use transpose. It's pretty close to @pamu's. I've borrowed diffPercent from @Marth's answer.

data.sliding(2)
    .map{case List(a, b) => (a zip b).map {case (x,y) => diffPercent(x,y)}}
    .toList
The Archetypal Paul
  • 41,321
  • 20
  • 104
  • 134
0

You may want to start by using from the transpose method and work the logic you need from there. Here is the result of calling transpose on your sample data:

scala> data.transpose.foreach(println)
List(Some(313.062468), Some(301.873641), Some(332.373186))
List(Some(27.847252), Some(42.884065), Some(53.509768))
List(Some(29.847252), Some(89.847252), Some(10.847252))
stefanobaghino
  • 11,253
  • 4
  • 35
  • 63
  • I see, so how would i fetch each element of each list in the transpose? – S. Nas Nov 18 '16 at 13:33
  • but then when flattened, the lists will be combined, which I don't want. I want to fetch the elements of the head of each list, then the next element in each list, and so on.. Just like columns. I want to fecth data in terms of column perspective – S. Nas Nov 18 '16 at 13:38
  • You can, for example, do something like ```data.transpose.map { case List(Some(a), Some(b), Some(c)) => /* your logic involving columns a, b and c */ ??? }``` – stefanobaghino Nov 18 '16 at 13:38
  • That's precisely what `transpose` does. Intuitively speaking, it turns rows into columns and viceversa. – stefanobaghino Nov 18 '16 at 13:39
  • Sorry for deleting the comment, I realized that was not what you wanted. – stefanobaghino Nov 18 '16 at 13:40
0

Transpose, flatten and zip

val list = data.transpose.flatMap(_.flatten)
list.tail zip list map { case (a, b) => (b - a)/b }

scala> val list = data.transpose.flatMap(_.flatten)
list: List[Double] = List(313.062468, 301.873641, 332.373186, 27.847252, 42.884065, 53.509768, 29.847252, 89.847252, 10.847252)

Scala REPL

scala> list.tail zip list map { case (a, b) => (b - a)/b }
res19: List[Double] = List(0.03573991820699504, -0.10103414428290529, 0.9162169116734945, -0.5399747522663995, -0.24777742035415723, 0.4422092803691468, -2.010235314125401, 0.8792700749489812)

Not a neat solution but works

data.zip(data.tail).map { case (alist, blist) => alist.flatten zip blist.flatten }.flatten.map { case (a, b) => (b - a)/b}

Important lines of code.

scala> data.zip(data.tail).map { case (alist, blist) => alist.flatten zip blist.flatten }.flatten
res4: List[(Double, Double)] = List((313.062468,301.873641), (27.847252,42.884065), (29.847252,89.847252), (301.873641,332.373186), (42.884065,53.509768), (89.847252,10.847252))

scala> data.zip(data.tail).map { case (alist, blist) => alist.flatten zip blist.flatten }.flatten.map { case (a, b) => (b - a)/b}
res5: List[Double] = List(-0.037064604126863805, 0.35063870460974256, 0.6678000569232768, 0.09176295286347183, 0.19857501531309202, -7.282950557431505)

Scala REPL

scala> var data = List(
     |       List(Some(313.062468), Some(27.847252), Some(29.847252)),
     |       List(Some(301.873641), Some(42.884065), Some(89.847252)),
     |       List(Some(332.373186), Some(53.509768), Some(10.847252))
     |     )
data: List[List[Some[Double]]] = List(List(Some(313.062468), Some(27.847252), Some(29.847252)), List(Some(301.873641), Some(42.884065), Some(89.847252)), List(Some(332.373186), Some(53.509768), Some(10.847252)))

scala> data.zip(data.tail)
res0: List[(List[Some[Double]], List[Some[Double]])] = List((List(Some(313.062468), Some(27.847252), Some(29.847252)),List(Some(301.873641), Some(42.884065), Some(89.847252))), (List(Some(301.873641), Some(42.884065), Some(89.847252)),List(Some(332.373186), Some(53.509768), Some(10.847252))))

scala> data.zip(data.tail).map { case (alist, blist) => alist zip blist }
res1: List[List[(Some[Double], Some[Double])]] = List(List((Some(313.062468),Some(301.873641)), (Some(27.847252),Some(42.884065)), (Some(29.847252),Some(89.847252))), List((Some(301.873641),Some(332.373186)), (Some(42.884065),Some(53.509768)), (Some(89.847252),Some(10.847252))))

scala> data.zip(data.tail).map { case (alist, blist) => alist zip blist }.flatten
res2: List[(Some[Double], Some[Double])] = List((Some(313.062468),Some(301.873641)), (Some(27.847252),Some(42.884065)), (Some(29.847252),Some(89.847252)), (Some(301.873641),Some(332.373186)), (Some(42.884065),Some(53.509768)), (Some(89.847252),Some(10.847252)))

scala> data.zip(data.tail).map { case (alist, blist) => alist zip blist }.flatten
res3: List[(Some[Double], Some[Double])] = List((Some(313.062468),Some(301.873641)), (Some(27.847252),Some(42.884065)), (Some(29.847252),Some(89.847252)), (Some(301.873641),Some(332.373186)), (Some(42.884065),Some(53.509768)), (Some(89.847252),Some(10.847252)))

scala> data.zip(data.tail).map { case (alist, blist) => alist.flatten zip blist.flatten }.flatten
res4: List[(Double, Double)] = List((313.062468,301.873641), (27.847252,42.884065), (29.847252,89.847252), (301.873641,332.373186), (42.884065,53.509768), (89.847252,10.847252))

scala> data.zip(data.tail).map { case (alist, blist) => alist.flatten zip blist.flatten }.flatten.map { case (a, b) => (b - a)/b}
res5: List[Double] = List(-0.037064604126863805, 0.35063870460974256, 0.6678000569232768, 0.09176295286347183, 0.19857501531309202, -7.282950557431505)
Nagarjuna Pamu
  • 14,737
  • 3
  • 22
  • 40