我正在做一个项目,我需要分配一个数组的值,并且这些值的总和必须是 100。
例子:
[70, 34, 92]
和总值100
。输出为[35.71, 17.35, 46.94]
因为35.71 + 17.35 + 46.94 = 100
。[86, 99.5, 100]
和总值100
。输出为[30.12, 34.85, 35.03]
。[96, 37]
和总值100
。输出为[72.18, 27.82]
。[98, 76.5, 68.5, 63.5, 38.5]
和总值100
。输出为[28.41, 22.17, 19.86, 18.41, 11.15]
= 100(sum)。
到目前为止我的解决方案:
- 对给定数组中的所有值求和
- 将每个值乘以 100
- 将每个值除以总和
- 使用
.toFixed(2)
。
“公式/计算”:+(((valueOfArray * 100)/totalSumOfGivenArray).toFixed(2))
我的第一个解决方案(小数问题所以 Not Acceptable ):
prioritySum = 0;
controlsKey.forEach((value) => {
priorityVal = this.getDistributedValue(+form.controls[formId].value, totalCatSum); // return +(((valueOfArray * 100) / totalSumOfGivenArray).toFixed(2))
prioritySum = prioritySum + priorityVal;
});
此解决方案有时不会准确返回 100 值。输出各种如 99.99、99.999999、100(大部分)、100.0000000001、99.999978、100.09999999、99.000009。这里有一些十进制数的问题。
我使用的另一种方法是:
let i = 0;
for(i = 0; i < controlsKey.length-1; i++){
let formId = controlsKey[i];
relValue = this.getDistributedValue(+form.controls[formId].value, totalActualSum); // returns formula result
form.controls[formId].setValue(relValue))
relativeSum = relativeSum + relValue;
}
relValue = 100 - relativeSum;
form.controls[controlsKey[i]].setValue(relValue)
这工作正常,但这个解决方案嗯...
所以我的问题是这个问题有什么优雅的解决方案吗?
第一个解决方案对我来说没问题,但即使我使用 .toFixed(2)
最佳答案
为了防止不需要的浮点值,您可以使用整数值并从 10000
的基值中减去该值(100 和两个位置)并创建一个字符串数组,其中点被插入获取格式化字符串的值。
const nice = s => s.toString().replace(/\d\d$/, '.$&');
function get100(array) {
var sum = array.reduce((a, b) => a + b),
offset = 1e4;
return array.map((v, j, { length }) => {
if (j + 1 === length) return nice(offset);
var i = Math.round(v * 1e4 / sum);
offset -= i;
return nice(i);
});
}
console.log(...get100([70, 34, 92])); // [35.71, 17.35, 46.94]
console.log(...get100([86, 99.5, 100])); // [30.12, 34.85, 35.03].
console.log(...get100([96, 37])); // [72.18, 27.82].
console.log(...get100([98, 76.5, 68.5, 63.5, 38.5])); // [28.41, 22.17, 19.86, 18.41, 11.15]
关于javascript - 给定数组 "distribute/scale"的数量到特定值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58959464/