1

This question might be duplicated, however, I've not come across any question that answers my problem.

So I have a List[ List[ Option[ Double ] ] ]

With the following data:

var tests = List(
  List(Some(313.062468), Some(27.847252)),
  List(Some(301.873641), Some(42.884065)),
  List(Some(332.373186), Some(53.509768))
)

I'd like to calculate this equation:

def findDifference(oldPrice: Option[Double], newPrice: Option[Double]): Option[Double] = {
    return Some(( newPrice.get - oldPrice.get ) / oldPrice.get)
}

on the following:

It's doing the calculation on the element of two lists:

(Some(301.062468) - Some(313.062468)) / Some(313.062468)

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

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

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

The result should return: #

List(
  List(Some(-0.03573991820699504), Some(0.5399747522663995))
  List(Some(0.10103414428290529), Some(0.24777742035415723))
)

My code so far

def findDifference(oldPrice: Option[Double], newPrice: Option[Double]): Option[Double] = {
    return Some(( newPrice.get - oldPrice.get ) / oldPrice.get)
}

def get_deltas(data: List[List[Option[Double]]]):  List[List[Option[Double]]] = {
  for {
    i <- data
    // So this is where I am stuck. I have the current element i, but I need the same index element in the next list
  } ( findDifference(i,?) }

My output If I print my I in For-comprehension

List(Some(313.062468), Some(27.847252))
List(Some(301.873641), Some(42.884065))
List(Some(332.373186), Some(53.509768))

Where Am I stuck?

I'm stuck in the fact that I don't know how to get the element of the same index in the list 1 from List 2 and List 3 and do the necessary calculation?

Please help me achieve my result output

S. Nas
  • 331
  • 1
  • 4
  • 14
  • What's the point of wrapping your values with `Some`, when you're unwrapping every possible value using `.get` in your `findDifference` method? – Paweł Jurczenko Nov 16 '16 at 17:30
  • 1 - You can't use a `for` comprehension in that manner if the index of the element is important. 2 - Your code will throw a runtime exception if any of those Options is `None`. (Which is what Options are for.) 3 - I think your data representation is far too complex. – jwvh Nov 16 '16 at 17:32
  • Ive added some to explain my issue. Its not required ot be inside. I just don't know how to do the calculation. Is there a way of doing it? @jwvh – S. Nas Nov 16 '16 at 17:33
  • @PawełJurczenko There is no point. ive just added it to explain my issue. – S. Nas Nov 16 '16 at 17:35
  • You're so close. See the point where you have `( findDifference(i,?) }`, it should be `( findDifference(i(0),i(1)) }`. My answer below pretty much says the same thing – airudah Nov 16 '16 at 17:58
  • @RobertUdah But that doesn't give me the right answer though? – S. Nas Nov 16 '16 at 18:40
  • I think the index values were the wrong way round. should instead be `findDifference(i(1),i(0))` – airudah Nov 17 '16 at 10:14

2 Answers2

0

Try to play with this:

object OptIdx {

  def main(args: Array[String]) {
    println(get_deltas(tests))
  }

  var tests = List(
    List(Some(313.062468), Some(27.847252)),
    List(Some(301.873641), Some(42.884065)),
    List(Some(332.373186), Some(53.509768)))

  def findDifference(oldPrice: Option[Double], newPrice: Option[Double]): Option[Double] = {
    Some((newPrice.get - oldPrice.get) / oldPrice.get)
  }

  def get_deltas(data: List[List[Option[Double]]]): List[List[Option[Double]]] = {
    (for {
      index <- 0 to 1
    } yield {
      (for {
        i <- 0 to data.length - 2
      } yield {
        findDifference(data(i)(index), data(i + 1)(index))
      }).toList
    }).toList
  }

}

It prints the numbers you want, but two of them are swapped. I'm sure you can figure it out, though.

radumanolescu
  • 4,059
  • 2
  • 31
  • 44
  • I like how you implemented this, and it works like a charm. But I've tried to look closely why its being swapped. No idea. Any clues? – S. Nas Nov 16 '16 at 18:39
  • @NaseebullahSafi: play with the indices, and with the values. Use numbers that you can verify by hand. Maybe you need to swap the outer loop and the inner, etc – radumanolescu Nov 16 '16 at 18:46
  • You deserve this question bro – S. Nas Nov 16 '16 at 19:06
0

So your data structure implies that i is a list of two options. The values you need are there already so you can call i(0) and i(1)

I've done a quick and dirty one in the repl:

scala> val tests = List(
     |   List(Some(313.062468), Some(27.847252)),
     |   List(Some(301.873641), Some(42.884065)),
     |   List(Some(332.373186), Some(53.509768))
     | )
tests: List[List[Some[Double]]] = List(List(Some(313.062468), Some(27.847252)), List(Some(301.873641), Some(42.884065)), List(Some(332.373186), Some(53.509768)))

And here you can see the value of i when I call:

scala> for { i <- tests } println(i)
List(Some(313.062468), Some(27.847252))
List(Some(301.873641), Some(42.884065))
List(Some(332.373186), Some(53.509768))

So you can call findDifference thus:

scala> def findDifference(oldPrice: Option[Double], newPrice: Option[Double]): Option[Double] = {
     | Option((oldPrice.get - newPrice.get) /oldPrice.get)
     | }
findDifference: (oldPrice: Option[Double], newPrice: Option[Double])Option[Double]

scala> for { i <- tests } println(findDifference(i(0), i(1)))
Some(0.911048896477747)
Some(0.8579403459740957)
Some(0.8390069648999904)
airudah
  • 1,169
  • 12
  • 19
  • There are better ways to structure your data. First you could create a case class `Prices(oldPrice: Option[Double], newPrice: Option[Double])` which should make your code easier to follow as you can call params by name, etc. If you are sure to always get a price, then you might not need to use options at all – airudah Nov 16 '16 at 17:55