-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月または)の値(つまり、内部リストの2番目の項目)を合計したいと思います。

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

8 に答える 8

11

私は反対を感じているので、ここに規定された方法のどれも使用しない答えがあります:groupBy、、またはslicecollectsum

回避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

問題を小さなステップに分割します。リストを毎月 1 つのリストに分割することから始めます。これに使用できます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、日付の月を確認する必要があるため
  • collectfilter、月ごと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 に答える