数组的加权平均值

问题描述 投票:0回答:4

我必须用 JavaScript 编写以下加权平均公式:

平均值 = (p1*p2*x1 + p3*p4*x2 + ... +p(n-2)*p(n-1)*xn) / (p1*p2 + p3*p4 + ... + p(n-2)p(n-1) )

公式给出

x
值的平均值。

我还有一个

array
在 JavaScript 中填充了
n
元素:

Array = (p1,p2,x1,p3,p4,x2....)

...其中

pi
是权重和
xi
我想要找到平均值的值。

如何使用这个数组编写公式?

javascript average weighted
4个回答
3
投票

我可能会使用以下策略:

  • 创建两个新数组(可能是
    weights
    values
    )。
  • 以3步迭代原始数组;乘以
    pn
    并将结果推入
    weights
    并将
    xn
    推入
    values
    .
  • 迭代新数组,创建加权总数(除法的左手)和总权重(除法的右手)。
  • 一个除以另一个。完成。

换句话说,是这样的:

function weighted_average(input) {
    var weights = [];
    var values = [];
    var weighted_total = 0;
    var total_weight = 0;;

    if (input.length % 3 !== 0) {
        throw new Error("Input array length is not a multiple of 3.");
    }

    for (var i = 0; i < input.length; i += 3) {
        weights.push(input[i] * input[i + 1]);
        values.push(input[i + 2]);
    }

    for (var i = 0; i < weights.length; i += 1) {
        weighted_total += weights[i] * values[i];
        total_weight += weights[i];
    }

    return weighted_total / total_weight;
}

不过,您必须验证这是否完全符合您的要求。没有保证。 ;)

JSFiddle 演示:jsfiddle.net/Z8seZ

当然,你可以跳过中间数组,让它更快一些。但上面的内容更明确,更易读,因此更易于维护(例如,您可以轻松地拆分实际算法并为不同形式的输入创建不同的“包装器”函数)。如果使用(真正的)大数据集,我只会优化它。


3
投票

这是一个函数式方法,需要 ES5:

var w = a.unzip(3).map(function(v, i, a) {
    var weight = v[0] * v[1];
    var sum = weight * v[2];
    return [sum, weight];
}).reduce(function(p, c, i, a) {
    return [p[0] + c[0], p[1] + c[1]];
}, [0, 0]);

var aw = w[0] / w[1];

在伪代码中是:

split the array into chunks of three
convert each three [p1, p2, x ] into a pair [ p1 * p2 * x , p1 * p2 ]
sum the pairs (along the array, not within each pair)
divide one by the other

以及将数组分块的(非标准)

unzip
函数是:

Object.defineProperty(Array.prototype, 'unzip', {
    value: function(n) {
        n = n || 2;
        return this.reduce(function(p, c, i, a) {
            if (i % n === 0) {
                p.push(a.slice(i, i + n));
            }
            return p;
        }, []);
    }
});

1
投票

ES6 单行对象数组

xs
包含键
w
作为权重和
v
作为值:

((_w, _v) => _v / _w)(...xs.reduce((r, o) => [r[0] + o[w], r[1] + o[w] * o[v]], [0, 0]))

0
投票

更清晰的 TypeScript 阅读解决方案:

.reduce<{ weightedSum: number; sum: number }[]>(
  (a, b) => [
    {
      weightedSum:
        a[0].weightedSum + b.value * b.weight,
      sum: a[0].sum + b.weight,
    },
  ],
  [{ weightedSum: 0, sum: 0 }]
)
.map((value) => value.weightedSum / value.sum)[0]

基本上你同时迭代计算分子和分母,然后在完成时除它。

© www.soinside.com 2019 - 2024. All rights reserved.