Using below code I'm attempting to produce
Map(2017-06-03 09:25:30 -> List( ("c",2190.79) , ("d",24.11), ("d",24.11), ("d",24.11) ),
2017-06-03 09:25:40 -> List( ("b",24.62) , ("b",24.62)) ,
2017-06-03 09:25:50 -> List( ("a",194.55) , ("a",194.55)) )
from
val l = List("a,194.55,2017-06-03 09:25:50",
"b,24.62,2017-06-03 09:25:40",
"c,2190.79,2017-06-03 09:25:30",
"d,24.11,2017-06-03 09:25:30",
"a,194.55,2017-06-03 09:25:50",
"b,24.62,2017-06-03 09:25:40",
"c,2190.79,2017-06-03 09:25:30",
"d,24.11,2017-06-03 09:25:30")
Here is complete code:
object Main extends App {
val l = List("a,194.55,2017-06-03 09:25:50",
"b,24.62,2017-06-03 09:25:40",
"c,2190.79,2017-06-03 09:25:30",
"d,24.11,2017-06-03 09:25:30",
"a,194.55,2017-06-03 09:25:50",
"b,24.62,2017-06-03 09:25:40",
"c,2190.79,2017-06-03 09:25:30",
"d,24.11,2017-06-03 09:25:30")
case class Details(date : java.util.Date , det : (String , Float))
val format = new java.text.SimpleDateFormat("yyyy-MM-dd hh:mm:ss")
val p = l.map(m => new Details(format.parse(m.split(",")(2)), ( m.split(",")(0),m.split(",")(1).toFloat) ))
val s = p.sortBy(r => (r.date))
val map = s.foldLeft(Map[java.util.Date, List[(String , Float)]]()) { (m, s) => (m , List(s)) }
}
Line:
val map = s.foldLeft(Map[java.util.Date, List[(String , Float)]]()) { (m, s) => (m , List(s)) }
is causing the following compilation error:
[error] found : (scala.collection.immutable.Map[java.util.Date,List[(String, Float)]], List[Main.Details]) [error] required: scala.collection.immutable.Map[java.util.Date,List[(String, Float)]] [error] val map = s.foldLeft(Mapjava.util.Date, List[(String , Float)]) { (m, s) => (m , List(s)) } [error]
^ [error] one error found [error] (compile:compileIncremental) Compilation failed [error] Total time: 2 s, completed 11-Jun-2017 22:51:46
Am I not using map
correctly?
The problem you are facing comes from the anonymous function you are trying to integrate a new tuple into your map; what you do is:
{ (m, s) => (m, List(s)) }
Where m
is of type Map[Date, List[(String , Float)]]
and s
is of type Details
.
The (m, List(s))
syntax means that you are creating a pair composed of the map m
and a singleton list that contains s
.
What you want to achieve, instead, is to put the two items in s
as a new pair of m
, something that you can achieve by doing the following:
{ (m, s) => m.updated(s.date, s.det :: m.get(s.date).getOrElse(List.empty)) }
Let's see what happens here: you take the accumulator map m
and update it at every turn of the fold with s.date
as the key and then a value. The value is the previously held value for that key (m.get(s.date)
, to make sure we're not overwriting that key) or an empty list if there is still no value, prepended with the value that we are looking at right now while the fold traverses the collection.
This solves the issue, but as you may see, what you are doing is a widely known operation of grouping and the Scala Collection API already provides you the basic infrastructure to achieve your objective.
You can refactor your code like follows and obtain the same result:
object Main extends App {
val l = List("a,194.55,2017-06-03 09:25:50",
"b,24.62,2017-06-03 09:25:40",
"c,2190.79,2017-06-03 09:25:30",
"d,24.11,2017-06-03 09:25:30",
"a,194.55,2017-06-03 09:25:50",
"b,24.62,2017-06-03 09:25:40",
"c,2190.79,2017-06-03 09:25:30",
"d,24.11,2017-06-03 09:25:30")
val format = new java.text.SimpleDateFormat("yyyy-MM-dd hh:mm:ss")
val map =
l.groupBy(m => format.parse(m.split(",")(2))).
mapValues(l => l.map(m => (m.split(",")(0),m.split(",")(1).toFloat)))
}
As you see, I've used the groupBy
combinator with the parse
method of your formatter. This function however presents as values of the resulting grouping the whole item, while you only wanted parts of it (which is why I further used the mapValues
combinator).
If you are further interested into the ordering in which your map exposes your items, remember to use a map that enforces some kind of ordering (like a SortedMap
).