Scala, Collect double case
Hi How to transform this
for (w <- m ){
val w = (w._2.collect {
case x if (x._2 > 0) => x._2;
case x if (x._2 < 0) => x._2 }) // if I add here .sum i got sum of (negative and positive) together
}
to get sum of positive and sum of negative values in one collect, it could be List(positive.sum,negative.sum) or two values
edit: only groupby, slice, collect, sum and yield
I wrote working program, but it' was not acepted, beacause it doing two collect
val m = d.groupBy(_._1.slice(0, 7))
for (w<- m) {
val x = (w._2.collect { case x if (x._2> 0) => x._2 }).sum
val y = (w._2.collect { case x if (x._2< 0) => x._2 }).sum
println("%7s %11.2f %11.2f %11.2f" format(w._1 , x , y ,(x+y)))
}
}
entry data are
val d = List(("2011-01-04", -137.76),
("2011-01-04", 2376.45),
("2011-01-04", -1.70),
("2011-01-04", -1.70),
("2011-01-04", -1.00),
("2011-01-06", 865.70),
("2011-01-07", -734.15),
("2011-01-05", -188.63),
("2011-01-06", -73.50),
("2011-01-07", -200.00),
("2011-01-09", -215.35),
开发者_StackOverflow中文版 ("2011-01-09", -8.86),
("2011-01-09", -300.00),
("2011-01-11", -634.54),
("2011-01-11", -400.00),
("2011-01-12", -92.87),
("2011-01-13", -1839.24),
("2011-01-13", 10000.00),
("2011-01-13", -10000.00),
("2011-01-15", -127.97),
("2011-01-15", -319.02),
("2011-01-19", -549.00),
("2011-01-21", -164.80),
("2011-01-23", -500.00),
("2011-01-25", -377.97),
("2011-01-26", 2158.66),
("2011-01-26", -130.45),
("2011-01-27", -350.00),
("2011-01-29", -500.00),
("2011-02-01", 2376.45),
("2011-02-01", 955.00))
I recognise this homework :)
So it looks like m is a Map
, and you don't much care about the keys in the output (perhaps you already used filterKeys by this point), so probably easiest to just pull out the values then filter - avoid all those tedious tuples and their underscores...
val values = m.values
val positives = values filter { _ >= 0 }
val negatives = values filter { _ < 0 }
Or if you prefer, this can be tidied up (and made more efficient) using the partition
method:
val (positives,negatives) = m.values partition { _ >= 0 }
or even use the co-called "point free" style, but that might be pushing it too far:
val (positives,negatives) = m.values partition { 0 < }
You shouldn't have any problem now figuring out what to do with positives
and negatives
Use recursion with an inner function utilizing an accumulator:
def sumIt(input:List[Tuple2[Int,Int]):Tuple2[Int,Int}={
def sum_vals(entries:List[Tuple2[Int,Int]], acc:Tuple2[Int,Int]):Tuple2[Int,Int]={
entries match{
case x::xs => if(x._2 < 0){
sum_vals(xs, (acc._1, acc._2+x._2))
}
else{
sum_vals(xs, (acc._1+x._2, acc._2))
}
case Nil => acc
}
}
sum_vals(input, (0,0))
}
Where I'm assuming you want all negative values held in the first item of the returned tuple and the negative in the second.
Edit:
FoldLeft, I need to think in terms of FoldLeft:
def sum_vals(left:Tuple2[Int,Int], right:Tuple2[Int,Int])={
if(right._2 < 0){
(left._1, left._2 + right._2)
}
else{
(left._1+right._2, left._2)
}
}
myCollection.foldLeft((0,0))( x,y => sum_vals(x,y) )
I assume you are using map of maps like Map[String, Map[String, Int]] in this case solution can look like this:
val m = Map("hello" -> Map("a" -> 1, "b" -> -5, "c" -> 3, "d" -> -2))
val sums = m map {
case (k, v) =>
k -> (v.values partition (_ > 0) match {
case (p, n) => (p.sum, n.sum)
}).productIterator.toList
}
println(sums)
and the output will look like this:
Map(hello -> List(4, -7))
if you still want to use for comprehension, it can look like this:
for (w <- m) {
val sums = (w._2.values.partition(_ > 0) match {
case (p, n) => (p.sum, n.sum)
}).productIterator.toList
}
(tested with Scala 2.8.1)
Here is solution:
val m = for ((k, v) <- d.groupBy(_._1.slice(0, 7))) yield k -> (for ((t, nums) <- (for ((s, l) <- (for ((date, num) <- v) yield (num, if (num > 0) 'positive else 'negative)).groupBy(_._2)) yield s -> (for ((num, _) <- l) yield num))) yield t -> nums.sum)
for ((month, nums) <- m; positive <- nums.get('positive) orElse Some(0D); negative <- nums.get('negative) orElse Some(0D)) {
println("%7s %11.2f %11.2f %11.2f" format(month, positive, negative, positive + negative))
}
it gives the same result as your solution and uses only slice, groupBy, sum, yield (who needs collect :). Now another trial - you should try to understand this :) (and may be optimize)
精彩评论