将数据组合成较小的离散间隔

时间:2015-02-01 03:51:43

标签: f# mapping intervals discrete-mathematics

假设我们有一对输入数组,或者你喜欢的(键,值)元组列表。什么是优雅和高效的方式来组合指数落在特定区间内的值?例如,如果间隔(或&#39; bin&#39;)大小为10,则0 < x <= 10的所有索引的值将合并,10 < x <= 20的索引值也会合并上。我想要:

let interval = 10
let index  = [| 6; 12; 18; 24 |]
let value  = [| a;  b;  c;  d |]
result = [| a; b + c; d |]

最粗略的方法是使用大量的if,else if语句(索引范围有一个定义的上限)。

我接近了
for i = 0 to index.Length do
    result.[Math.Floor(index.[i]/10] += value.[Math.Floor(index.[i]/10]

但这是0 <= x < 10,而不是0 < x <= 10

我还尝试假设索引是有序且均匀分布的,

for i = 1 : ( index.Length - 1 ) / valuesPerBin
    valueRange = ((i-1)*valuesPerBin + 1) : i*valuesPerBin )
    result(i) = sum(value(valueRange))

这很好但是如果每个bin有一个非整数值的话,它会明显中断。

在F#中执行此操作的最佳方法是什么?是否有我想要做的名称或现有功能?

2 个答案:

答案 0 :(得分:1)

let interval = 10 
let index = [6;12;18;24] 
let value =[101;102;103;104] 
let intervals = List.map (fun e -> e/interval) index
let keys = List.map2(fun e1 e2 -> (e1,e2)) intervals value
let skeys = Seq.ofList keys
let result = skeys
             |>Seq.groupBy (fun p -> fst p) 
             |>Seq.map (fun p -> snd p)
             |>Seq.map(fun s -> Seq.sumBy (fun p -> snd p) s)

结果 将是[ 101; 205; 104 ](作为Seq)。

如果要转换为数组,请应用Seq.toArray。

这是你想要的吗?

答案 1 :(得分:0)

调整要使用的周围代码 0 <= x < 10代替0 < x <= 10。在我的情况下,这只是另一个函数的简单定义更改,允许我使用 for i = 0 to index.Length do result.[Math.Floor(index.[i]/10] += value.[Math.Floor(index.[i]/10],这比其他选择更简单,更简洁。