我有以下数组:
var myNumbers = [70.37037037037037, 11.11111111111111, 11.11111111111111, 7.4074074074074066];
我需要对每个数字进行舍入,并将它们的总和全部归为100.如果它们不足,则差异将通过按小数部分的降序向项目添加1来弥补。这称为Largest Remainder Method
(我得到以下代码形式How to make rounded percentages add up to 100%)。以下是下划线代码:
var off = 100 - _.reduce(myNumbers, function(acc, x) {
return acc + Math.round(x)
}, 0);
var rounded_percentages = _.chain(myNumbers)
.sortBy(function(x) {
return Math.round(x) - x
})
.map(function(x, i) {
return Math.round(x) + (off > i) - (i >= (myNumbers.length + off))
})
.value();
结果是:
[8, 70, 11, 11]
这很好但订单不会保留。如何在保留顺序或使用对象而不是数组执行整个操作并保留正确的键映射的情况下实现上述目的?
保留订单后,应该产生:
[70, 11, 11, 8]
使用键映射,初始var看起来像:
var myNumbers = {
firstNum: 70.37037037037037,
secondNum: 11.11111111111111,
thirdNum: 11.11111111111111,
fourthNum: 7.4074074074074066
};
,结果将是:
{
fourthNum: 8,
firstNum: 70,
secondNum: 11,
thirdhNum: 11
};
答案 0 :(得分:2)
根本不要改变数组的顺序。只创建一个排列(一个索引数组,然后按每个索引指向的数组值的属性排序),并在其上播放您的算法。
var rounded_percentages = _.map(myNumbers, Math.floor);
var off = _.reduce(rounded_percentages, function(acc, x) { return acc - x; }, 100);
var permutation = _.sortBy(_.map(myNumbers, function(_, i) { return i; }), function(i) {
return rounded_percentages[i] - myNumbers[i]; // those with the largest diff first
});
for (var i=0; i<off; i++)
rounded_percentages[permutation[i]]++
这是最大剩余方法的更接近的实现,您的实现中的Math.round
是奇数。