我有天在本月的列表:在斯卡拉,我如何摺疊列表並返回中間結果?
val days = List(31, 28, 31, ...)
我需要與天的累計總和返回一個列表:
val cumDays = List(31, 59, 90)
我想到了用摺疊操作的:
(0 /: days)(_ + _)
但這隻會返回最終結果(365),而我需要中間結果列表。
無論如何,我能做到這一點優雅?
我有天在本月的列表:在斯卡拉,我如何摺疊列表並返回中間結果?
val days = List(31, 28, 31, ...)
我需要與天的累計總和返回一個列表:
val cumDays = List(31, 59, 90)
我想到了用摺疊操作的:
(0 /: days)(_ + _)
但這隻會返回最終結果(365),而我需要中間結果列表。
無論如何,我能做到這一點優雅?
斯卡拉2.8所擁有的方法scanLeft
和scanRight
它這樣做。
2.7,你可以定義自己的scanLeft
這樣的:
def scanLeft[a,b](xs:Iterable[a])(s:b)(f : (b,a) => b) =
xs.foldLeft(List(s))((acc,x) => f(acc(0), x) :: acc).reverse
,然後用它是這樣的:
scala> scanLeft(List(1,2,3))(0)(_+_)
res1: List[Int] = List(0, 1, 3, 6)
文選2.7.7:
def stepSum (sums: List [Int], steps: List [Int]) : List [Int] = steps match {
case Nil => sums.reverse.tail
case x :: xs => stepSum (sums.head + x :: sums, steps.tail) }
days
res10: List[Int] = List(31, 28, 31, 30, 31)
stepSum (List (0), days)
res11: List[Int] = List(31, 59, 90, 120, 151)
摺疊列表成爲一個新列表。在每次迭代中,附加一個值,該值是頭+下一個輸入的總和。然後扭轉整個事情。
scala> val daysInMonths = List(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
daysInMonths: List[Int] = List(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
scala> daysInMonths.foldLeft(Nil: List[Int]) { (acc,next) =>
| acc.firstOption.map(_+next).getOrElse(next) :: acc
| }.reverse
res1: List[Int] = List(31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365)
我不知道爲什麼每個人似乎都堅持使用某種摺疊式的,而你基本上要值映射到累積值...
val daysInMonths = List(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
val cumulated = daysInMonths.map{var s = 0; d => {s += d; s}}
//--> List[Int] = List(31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365)
你可以簡單地進行它:
daysInMonths.foldLeft((0, List[Int]()))
{(acu,i)=>(i+acu._1, i+acu._1 :: acu._2)}._2.reverse
您還可以創建連接兩個列表,同時增加了第二個從第一的最後一個值幺類。沒有可變參數和摺疊參與:
case class CumSum(v: List[Int]) { def +(o: CumSum) = CumSum(v ::: (o.v map (_ + v.last))) }
defined class CumSum
scala> List(1,2,3,4,5,6) map {v => CumSum(List(v))} reduce (_ + _)
res27: CumSum = CumSum(List(1, 3, 6, 10, 15, 21))
謝謝,但我現在只能使用Scala 2.7 ... – lindelof 2010-07-11 23:07:09
最後!我真的不能相信這個共同的問題沒有現成的抽象。感謝您指出了這一點。 – MEMark 2013-04-21 13:25:23
另外'List(1,2,3).scanLeft(0)(_ + _)'。 – Jus12 2014-03-16 19:49:51