给出如下列表:
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)
)
我想按照指定的顺序使用以下操作对特定月份(例如1月或01
)的值(即内部列表的第二项)求和:
groupBy
slice
collect
sum
答案 0 :(得分:11)
我感觉相反,所以这是一个使用NONE规定方法的答案:groupBy
,slice
,collect
或sum
避免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 {_+_}
答案 1 :(得分: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))
}
}
答案 2 :(得分: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
答案 3 :(得分:4)
将问题分解为更小的步骤。首先尝试将列表拆分为每月一个列表。您可以使用groupBy
。您的第一个问题可能是如何解析日期字符串。一般的解决方案是使用自定义日期类和正则表达式;然而,在这种情况下,使用索引子字符串(或slice
)的更简单的临时解决方案可能是合适的。
一般提示是将数据加载到Scala REPL中并使用它。祝你好运。
答案 4 :(得分: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
最终显示为从月份编号到总数的地图。
答案 5 :(得分:3)
所以,这是一个想法:
groupBy
,因为您需要将每个月的数据分组在一起slice
,因为您需要查看哪个是日期月份collect
,因为您需要filter
按月和map
进行评估sum
,mmmm ......我不确定这个进来的地方。有什么想法吗?答案 6 :(得分: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
}
答案 7 :(得分:0)
dane.groupBy (_._1.matches (".*-01-.*")).slice (0, 1).map (x => x._2).flatten .map (y => y._2).sum
我真的应该查找'收集',以某种方式取代我的地图/展平/地图。
我的结果是:Double = 2234.29