2010-02-24 23 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