2010-02-24 21 views
2

假設我有n個數組,其中n是一個變量(某個數大於2,通常小於10)。如何將函數應用於浮點數組?

每個陣列具有k個元素。

我也有長度爲n的數組,其中包含一組權重是決定我想怎麼線性組合所有的陣列。

我想創建一個高性能的高階功能,這些陣列在F#結合。

如何可以做到這一點,這樣我得到一個函數,它接受一個數組的數組(ARRS是樣本),一個權重陣列(權重),然後計算基於所述權重的加權和?

let weights = [|.6;;.3;.1|] 

let arrs = [| [|.0453;.065345;.07566;1.562;356.6|] ; 
       [|.0873;.075565;.07666;1.562222;3.66|] ; 
       [|.06753;.075675;.04566;1.452;3.4556|] |] 

感謝您的任何想法。

+0

你能舉一個例子輸出嗎?我不清楚,如果你最後只需要一個數字,或者k個數組與n個元素的總和。 – Benjol 2010-02-24 19:30:47

回答

6

這裏有一個解決方案:

let combine weights arrs = 
    Array.map2 (fun w -> Array.map ((*) w)) weights arrs 
    |> Array.reduce (Array.map2 (+)) 

編輯

這裏是如何工作的一些(急需)的解釋。從邏輯上說,我們想要做到以下幾點:

  1. 將每個權重應用到其對應的行。
  2. 將重量調整過的行相加在一起。

上面的兩行做到這一點。

  1. 我們使用Array.map2函數來組合相應的權重和行;我們將它們結合的方式是將行中的每個元素乘以權重,這是通過內部Array.map來實現的。
  2. 現在我們有一個加權行數組,需要將它們加在一起。我們可以一次完成一個步驟,保持運行總和,依次添加每個數組。我們按點分數總結兩個數組的方式是再次使用Array.map2,使用(+)作爲組合每個元素的函數。我們用Array.reduce來包裝這個函數,將這個加法函數依次應用到每一行,從第一行開始。

希望這是一個相當優雅的方法來解決這個問題,雖然無點式的風格承認它使得它有點棘手。但是,請注意,這不是特別高效;進行就地更新而不是創建新的陣列,每個應用程序mapmap2reduce會更有效。不幸的是,標準庫並不包含就地工作的這些操作的很好的類比。然而,創建這樣的類似物相對容易,而且它們的使用方式可能與我在此處完成的方式幾乎完全相同。

+0

我更喜歡你的。我仍然很瞭解F#。 – 2010-02-24 20:30:13

+0

@大衛 - 謝謝。標準庫中有很多有用的組合器,它通常只是一個如何組合它們以獲得所需內容的問題。 – kvb 2010-02-24 20:43:44

+0

@kvb,這可以做一些解釋。我花了一段時間纔算出第一個map2函數的第二個參數去了哪裏。它應該是'T1 - >'T2 - >'U,但我只看到w。如果我已經理解正確,map2函數的部分應用權重產生了另一個應用於arrs的函數? (腦爆炸) – Benjol 2010-02-25 05:57:42

1

像這樣的東西爲我做:

let weights = [|0.6;0.3;0.1|] 

let arrs = [| [|0.0453;0.065345;0.07566;1.562;356.6|] ; 
       [|0.0873;0.075565;0.07666;1.562222;3.66|] ; 
       [|0.06753;0.075675;0.04566;1.452;3.4556|] |] 

let applyWeight x y = x * y 

let rotate (arr:'a[][]) = 
    Array.map (fun y -> (Array.map (fun x -> arr.[x].[y])) [|0..arr.Length - 1|]) [|0..arr.[0].Length - 1|] 

let weightedarray = Array.map (fun x -> Array.map(applyWeight (fst x)) (snd x)) (Array.zip weights arrs) 

let newarrs = Array.map Array.sum (rotate weightedarray) 

printfn "%A" newarrs 

順便說.. 0前面的浮點值是必要的。

+0

這太棒了。感謝大衛! – 2010-02-24 19:38:41