2012-08-08 124 views
1

我不得不使用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

我也有JavaScript和n元素填充的array

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

...其中pi是权重和xi值我想找到平均值。如何使用这个数组写入公式?

+0

您能给出示例值吗? 向我们展示一个具有真实世界值的计算结果,并且您期望 – Tschallacka 2012-08-08 14:38:56

+0

的结果是否必须让您的'p'和'x'值以这种方式交错? – Alnitak 2012-08-08 14:39:12

+0

你在x之前总是有2 p还是可以改变? – Youssef 2012-08-08 14:41:04

回答

1

我可能会使用以下策略:

  • 创建两个新的阵列(大概weightsvalues)。
  • 以3为单位迭代原始数组;乘以pn's并将结果推入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

当然,你可以跳过中介阵列让它快一点。但是,上述内容更加明确,更具可读性,因此更易于维护(例如,您可以轻松分割出实际的算法并为不同形式的输入创建不同的“包装”功能)。如果使用(真的)大型数据集,我只会优化它。

+0

美丽!谢谢! – multigoodverse 2012-08-11 10:04:44

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; 
     }, []); 
    } 
}); 
+0

哇。这很让人佩服。花了我一段时间阅读,虽然...你是一个Perl程序员? :P – PPvG 2012-08-08 16:20:18

+1

@PPvG我已经涉足Perl,但这种方法更多的是功能语言,如Erlang,Haskell和LISP。 – Alnitak 2012-08-08 16:41:52

1

ES6对于一系列对象的单线程xs包含键为w as weight,v as value:

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