在this question中,我遇到了以下简化问题:
我们从具有value属性的Objects数组开始。我们要为每个值计算它是值总和的百分比,并将其作为属性添加到结构中。为此,我们需要知道值的总和,但是不会预先计算出该总和。
//Original data structure
[
{ "value" : 123456 },
{ "value" : 12146 }
]
//Becomes
[
{
"value" : 123456,
"perc" : 0.9104
},
{
"value" : 12146 ,
"perc" : 0.0896
}
]
一个简单且可能是最易读的解决方案是两次遍历数据结构。首先我们计算总和,然后计算百分比并将其添加到数据结构中。
var i;
var sum = 0;
for( i = 0; i < data.length; i++ ) {
sum += data[i].value;
}
for( i = 0; i < data.length; i++ ) {
data[i].perc = data[i].value / sum;
}
我们是否可以只对数据结构进行一次遍历,并以某种方式告诉百分比表达式仅应在知道总和后才求值?
我主要对解决纯JavaScript的答案感兴趣。即:没有任何库。
最佳答案
一种减少循环的方法是写出由所有可能项目组成的整个sum语句,例如
var sum = (data[0] ? data[0].value : 0) +
(data[1] ? data[1].value : 0) +
(data[2] ? data[2].value : 0) +
...
(data[50] ? data[50].value : 0);
for( i = 0; i < data.length; i++ ) {
data[i].perc = data[i].value / sum;
}
并不是说这实际上是一个真正的解决方案您可以使用Array的reduce函数,但是在后台仍然是一个循环,并对每个数组元素进行函数调用:
var sum = data.reduce(function(output,item){
return output+item.value;
},0);
for( i = 0; i < data.length; i++ ) {
data[i].perc = data[i].value / sum;
}
您可以使用ES6 Promise,但是您仍然在其中添加了一堆函数调用var data = [
{ "value" : 123456 },
{ "value" : 12146 }
]
var sum = 0;
var rej = null;
var res = null;
var def = new Promise(function(resolve,reject){
rej = reject;
res = resolve;
});
function perc(total){
this.perc = this.value/total;
}
for( i = 0; i < data.length; i++ ) {
def.then(perc.bind(data[i]));
sum+=data[i].value;
}
res(sum);
Perf Tests