-2

给定如下列表:

val dane = 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),
    // ... skip a few ...
    ("2011-12-22", -178.02),
    ("2011-12-29", 1800.82),
    ("2011-12-23", -83.97),
    ("2011-12-24", -200.00),
    ("2011-12-24", -30.55),
    ("2011-12-30", 728.00)
)

我想01按指定的顺序使用以下操作对特定月份(例如一月或)的值(即内部列表的第二项)求和:

  1. groupBy
  2. slice
  3. collect
  4. sum
4

8 回答 8

11

我感觉相反,所以这是一个不使用任何规定方法的答案:groupBy, slice,collectsum

避免collect是最难的部分,condOpt/flatten实在是太丑陋了……

val YMD = """(\d\d\d\d)-(\d\d)-(\d\d)""".r

import PartialFunction._

(dane map {
  condOpt(_:(String,Double)){ case (YMD(_,"01",_), v) => v }  
}).flatten reduceLeft {_+_}
于 2011-01-21T12:24:14.550 回答
8
(for((YearMonthDay(_, 1, _), value)<-dane) yield value).sum

object YearMonthDay{
   def unapply(dateString:String):Option((Int, Int, Int)) ={ 
       //yes, there should really be some error checking in this extractor 
       //to return None for a bad date string
       val components = dateString.split("-")
       Some((components(0).toInt, components(1).toInt, components(2).toInt)) 
  }  

}
于 2011-01-21T15:26:42.657 回答
5

既然凯文已经开始了相反答案的趋势,这是你永远不应该使用的一个,但是天哪,它有效!(并且避免了每个请求的方法,并且如果您更改字符串,它将在任何月份工作,但它确实要求列表按日期排序。)

dane.scanLeft(("2011-01",0.0))((l,r) =>
  ( l._1,
    if ((l._1 zip r._1).forall(x => x._1==x._2)) l._2+r._2 else 0.0
  )
).dropWhile(_._2==0).takeWhile(_._2 != 0.0).reverse.head._2
于 2011-01-21T12:57:40.357 回答
4

把问题分解成更小的步骤。首先尝试将列表拆分为每个月的一个列表。你可以用groupBy这个。您的第一个问题可能是如何解析日期字符串。一般的解决方案是使用自定义日期类和正则表达式;但是,在这种情况下,使用索引子字符串(或)的更简单的临时解决方案slice可能是合适的。

一般提示是将数据加载到 Scala REPL 中并使用它。祝你好运。

于 2011-01-21T12:27:49.497 回答
3
import scala.collection.mutable.HashMap
val totals = new HashMap[Int, Double]
for (e <- dane) {
    val (date, value) = e
    val month = date.drop(5).take(2).toInt
    totals(month) = totals.getOrElse(month,0.0) + value
}

另一种实现不使用任何建议的功能,可变集合以及一些程序和功能风格的混蛋,避免了一些有用的功能:)

totals最终成为从月数到总数的地图。

于 2011-01-21T13:32:16.867 回答
3

所以,这里有一个想法:

  • groupBy,因为您需要将每个月的数据组合在一起
  • slice,因为您需要查看日期的月份
  • collect,因为你需要filter按月map计算
  • sum,嗯...我不确定这个是从哪里来的。有什么想法吗?
于 2011-01-21T21:29:15.540 回答
2

我拒绝混淆sum

import org.joda.time.DateMidnight
for (month <- 1 to 12) yield {
  dane map { case (d,v) => new DateMidnight(d).getMonthOfYear -> v }
  filter { case (m, v) => m == month }
  map (_._2)
  sum
}
于 2011-01-21T14:39:28.380 回答
0
dane.groupBy (_._1.matches (".*-01-.*")).slice (0, 1).map (x => x._2).flatten .map (y => y._2).sum

我真的应该查找“收集”,它应该以某种方式替换我的地图/展平/地图。

我的结果是:双 = 2234.29

于 2011-06-02T08:39:57.787 回答