1

嗨如何改变这个

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 }

要在一个集合中获得正值的总和和负值的总和,它可以是 List(positive.sum,negative.sum) 或两个值

编辑:只有 groupby、slice、collect、sum 和 yield

我写了工作程序,但它没有被接受,因为它做了两个收集


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)))
    }
}
输入数据是

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), ("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))

4

4 回答 4

3

我认识这个作业:)

所以看起来 m 是 a Map,并且您不太关心输出中的键(也许此时您已经使用了 filterKeys ),所以可能最简单的方法是提取值然后过滤 - 避免所有那些乏味的元组和他们的下划线...

val values = m.values
val positives = values filter { _ >= 0 }
val negatives = values filter { _ < 0 }

或者,如果您愿意,可以使用以下方法整理(并提高效率)partition

val (positives,negatives) = m.values partition { _ >= 0 }

甚至使用所谓的“无点”样式,但这可能会太过分:

val (positives,negatives) = m.values partition { 0 < }

你现在不应该有任何问题弄清楚如何处理positivesnegatives

于 2011-01-23T15:04:02.247 回答
1

这是解决方案:

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))
}

它给出的结果与您的解决方案相同,并且仅使用 slice、groupBy、sum、yield(谁需要收集 :)。现在进行另一次试验-您应该尝试理解这一点:)(并且可能会进行优化)

于 2011-01-23T16:36:31.820 回答
1

使用带有累加器的内部函数的递归:

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))
}

我假设您希望所有负值都保存在返回的元组的第一项中,而负值则保存在第二项中。

编辑:

FoldLeft,我需要从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) )
于 2011-01-23T14:30:28.543 回答
1

我假设您正在使用 Map[String, Map[String, Int]] 之类的地图,在这种情况下,解决方案可能如下所示:

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)

输出将如下所示:

Map(hello -> List(4, -7))

如果您仍想用于理解,它可以如下所示:

for (w <- m) {
  val sums = (w._2.values.partition(_ > 0) match {
    case (p, n) => (p.sum, n.sum)
  }).productIterator.toList
}

(使用 Scala 2.8.1 测试)

于 2011-01-23T15:15:44.043 回答