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

Combine data into smaller discrete intervals

假设我们有一对输入数组,或者如果您愿意,可以有一个(键,值)元组列表。什么是将索引落在特定区间内的值组合起来的优雅且高效的方法?例如,如果间隔(或 'bin')大小为 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# 中执行此操作的最佳方法是什么?有我想做的事情的名称或现有功能吗?

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)

result 将是 [101;205;104](作为 Seq) .

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

是你想要的吗?

适配周边代码使用 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],这比替代方法更简单、更简洁。