如何根据另一个数组中的值平均一个数组中的元素?

时间:2010-02-24 19:26:46

标签: f#

let tiedArray = [|9.4;1.2;-3.4;-3.4;-3.4;-3.4;-10.0|];

let sortedArray = [|-10.0;-3.4;-3.4;-3.4;-3.4;1.2;9.4|];
let sortedArrayRanks = [|1.;2.;3.;4.;5.;6.;7.|];

let desired_ranked_array = [|1.;3.5;3.5;3.5;3.5;6.;7.|] 

您好 -

我正在尝试编写一个带有2个数组(sortedArray和sortedArrayRanks)的函数,并返回一个如下所示的输出数组。此示例中的映射函数将在sortedArrayRanks中使用2,3,4和5,并且看到它们在sortedArray中都具有相同的值,而是将它们中的所有这些数字替换为它们的平均值(即3.5) )

让我兴奋的是,是使用递归还是命令性循环结构,比如循环遍历排序数组,并查看项目是否与之前的项目相同,然后如果匹配,请检查前面的项目,等等这怎么解决?谢谢!

2 个答案:

答案 0 :(得分:2)

这与F# How to Percentile Rank An Array of Doubles?非常相似。以下是我对该问题的回答的变体:

let rank arr (ranks:float[]) =
let rev = Array.rev arr
let len = Array.length arr
let first x = Array.findIndex (fun y -> y = x) arr
let last x = len - (Array.findIndex (fun y -> y = x) rev) - 1
let avgR x = ranks.[(first x) .. (last x)] |> Array.average
Array.map avgR arr

这假定arr已排序,arr中的元素支持相等比较。

答案 1 :(得分:0)

你可以:

  • 拉链元素及其等级
  • 按元素值
  • 对这些对进行分组
  • 平均组排名
  • 将结果表示为数组

记下那个算法作为剧本:

let f sortedArray sortedArrayRanks =
  [|
    for v,xs in Array.zip sortedArray sortedArrayRanks |>  Seq.groupBy (fun (v,r) -> v) do
      let n,r = Seq.fold (fun (n,r) (_,r') -> (n+1,r+r')) (0,0.) xs
      let r = r/(float n)
      for i in 1..n do yield r
  |]

> f [|-10.0;-3.4;-3.4;-3.4;-3.4;1.2;9.4|] [|1.;2.;3.;4.;5.;6.;7.|];;
val it : float [] = [|1.0; 3.5; 3.5; 3.5; 3.5; 6.0; 7.0|]