0

I'm pretty sure this question might be duplicated, but I haven't come across the answer for this. Please pardon my ignorant knowledge of Scala. I'm pretty newbie.

My aim is to loop over two lists (with different length) and return List[List[Option[Double]]].

My code so far:

 def getDoubles(symbol: String, year: Int): Option[Double] = {
   return Some(140.0)
 }

 // this method loops over list of strings and range of time. returns list of list of Option[Double]
 def checkList(CSV: List[String], time: Range): List[List[Option[Double]]] = {
   // this variable is whats going to be returned at the end
   var listOfLists = List[List[Option[Double]]]()
     // So we are going to loop over our list and our time, and link each element in our list to all the elements in          our time range
   for {
     i < -CSV
     j < -time
       // the method getDoubles is pretty long, so i just made another version simplfying my question.
       // get doubles bascially returns Option of doubles
   }
   yield (listOfLists = getDoubles(j, i)::listOfLists)
   return listOfLists
 }

The above code, when I call it with more sophisticated data, it returns:

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

But I want to return something like this:

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

How can I do this?

laughedelic
  • 6,230
  • 1
  • 32
  • 41
  • This case is simple, but in future you should provide a piece of your "sophisticated data" (: as an example and desired output for it, so that people can can easily try it in their answers' code. – laughedelic Nov 16 '16 at 02:30

1 Answers1

3

You don't need to use any mutable variables for this. First of all, you if you need a nested list, you need a nested for. Then in yield you should write how looks each element of the collection produced by this for. It's not a loop body, you're not supposed to do any mutations there. The whole for-expression is the resulting collection. Check Scala FAQ on "How does yield work?".

def checkList(csv: List[String], time: Range): List[List[Option[Double]]] = {
  for {
    symbol <- csv
  } yield {
    for {
      year <- time.toList
    } yield getDoubles(symbol, year)
  }
}

For-comprehension is just a syntax sugar for a combination of map, flatMap andfilter. In this case writing it with map is more concise and very straightforward:

def checkList(csv: List[String], time: Range): List[List[Option[Double]]] = {
  csv map { symbol =>
    time map { year =>
      getDoubles(symbol, year)
    }
  }
}

See also "What is Scala's yield?" question.

Community
  • 1
  • 1
laughedelic
  • 6,230
  • 1
  • 32
  • 41
  • 1
    Well explained, with references, no "beating around the bush", with clear explanation of For-comprehension. Everything you said was on point, and your solution made a clear understanding of where my confusion was. I solute you. –  Nov 16 '16 at 08:07