[英]Scala: How do I calculate the variance of a Seq[Double] using flatMap and Options?
我正在嘗試解決Scala中的“簡單”練習。 我有這個功能:
def mean(xs: Seq[Double]): Option[Double] =
if (xs.isEmpty) None
else Some(xs.sum / xs.length)
這是練習的內容:
練習2:根據均值和平面圖實現方差函數(如果均值為m,方差是math.pow(x - m,2)的平均值,請參見定義)。
我在想類似的東西
val xs = List(1.3,2.1,3.2)
val m = mean(xs)
xs flatMap(x=> math.pow(x-m,2)).mean //error!
什么是正確的解決方法? 如果可能的話,我也想要一個小的理論解釋
我不會這么簡單。
map
上Option[A]
取一個函數A => B
並返回一個Option[B]
是一種Some
如果原來是一個Some
和None
否則。 所以Some(2).map(_+2)
給出Some(4)
,但None[Int].map(_+2)
給出None。
flatMap
大致相同,但它需要一個函數A => Option[B]
並仍然返回一個Option[B]
。 如果原始為None
或給定函數導致None
,則結果為None
否則為Some[B]
。
你不想flatMap
在列表中,要flatMap
的選項。 我會給你一個提示,它開頭是:
mean(xs).flatMap(m => ...
在那個箭頭之后, m
是Double
,而不是Option[Double]
。
編輯:
好吧,很好,既然我們得到了所有的貶低而且沒有幫助,這就是完整的答案:
def variance(xs: Seq[Double]): Option[Double] = {
mean(xs).flatMap(m => mean(xs.map(x => Math.pow(x-m, 2))))
}
Matt Putnam的回答提供了一些很好的指示。 通過將其分解為更小的塊,我發現更容易理解這個問題。
scala> val xs = List(1.3,2.1,3.2)
xs: List[Double] = List(1.3, 2.1, 3.2)
scala> def mean(xs: Seq[Double]): Option[Double] = {
| if (xs.isEmpty) None
| else Some(xs.sum / xs.length)
| }
mean: (xs: Seq[Double])Option[Double]
計算每個元素與序列平均值的偏差:
scala> mean(xs).map(m => xs.map(x => x-m))
res0: Option[List[Double]] = Some(List(-0.9000000000000001, -0.10000000000000009, 1.0))
map
有效的,因為如果mean(xs)
是Some
,則計算x => xm
。 否則它不是,我們得到None
。
現在計算與序列平均值的平方偏差:
scala> mean(xs).map(m => xs.map(x => math.pow(x-m, 2)))
res1: Option[List[Double]] = Some(List(0.8100000000000003, 0.010000000000000018, 1.0))
然后計算那個的平均值:
scala> mean(xs).map(m => mean(xs.map(x => math.pow(x-m, 2))))
res2: Option[Option[Double]] = Some(Some(0.6066666666666668))
但在這里我們有一個Option
包含一個Option
,所以我們使用flatMap
拿到第一的價值Some
。 所以具有所需返回類型Option[Double]
的解決方案是:
scala> mean(xs).flatMap(m => mean(xs.map(x => math.pow(x-m, 2))))
res3: Option[Double] = Some(0.6066666666666668)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.