Javascript 保持数字总和为常数,同时确保每个数字都有一个最小值

Javascript 保持数字总和为常数,同时确保每个数字都有一个最小值,javascript,math,underscore.js,Javascript,Math,Underscore.js,我有一个对象,它的数值总和不能超过100%。但是,我希望每个数字必须有一个最小值(比如说5%);这基本上意味着,如果数组中的某个数字为0,则将其设置为5%,然后将该数量分配给所有其他大于0的数字 显然,一个问题是,这可能导致一个数字最初为6%,然后实际上降低到最小值以下的情况 目前,我的解决方案是: 这是可行的,但是,它非常丑陋。我相信有一种更好、更干净、更可扩展的方法可以做到这一点 一个数字最初是6%,然后实际上降低到最小值以下 你可以试着只减少5%以上的部分 var numbers = {…

我有一个对象,它的数值总和不能超过100%。但是,我希望每个数字必须有一个最小值(比如说5%);这基本上意味着,如果数组中的某个数字为0,则将其设置为5%,然后将该数量分配给所有其他大于0的数字

显然,一个问题是,这可能导致一个数字最初为6%,然后实际上降低到最小值以下的情况

目前,我的解决方案是:

这是可行的,但是,它非常丑陋。我相信有一种更好、更干净、更可扩展的方法可以做到这一点

一个数字最初是6%,然后实际上降低到最小值以下

你可以试着只减少5%以上的部分

var numbers = {…},
    adjusted = {};

var min = 5,
    sum = 0,
    count = 0,
    below = 0,
    belowCount = 0;
_.each(numbers, function(k, num) {
    sum += num;
    count++;
    if (num < min) {
        below += num;
        belowCount++;
    }
});
var aim = sum - min * count;
if (aim < 0)
    throw "Too many values, giving every the minimum would exceed sum";
var overMin = sum - below - (count-belowCount) * min,
    ratio = aim / overMin;
_.each(numbers, function(key, num) {
    if (num <= min)
        adjusted[key] = min;
    else
        adjusted[key] = min + (num - min) * ratio;
});
var number={…},
调整={};
var最小值=5,
总和=0,
计数=0,
低于=0,
低于计数=0;
_.每个(数字、函数(k、num){
sum+=num;
计数++;
if(numif(num)0%到5%之间的值会发生什么情况?为什么不能根据它们的值进行分配。例如,从较高的值中扣除较大的数字,从较低的值中扣除较小的数字。如果该值小于最小值(例如5%),不是吗然后它被设置为5%,其他超过最小值的值被相应地减少,以确保总数为100%?谢谢你,Bergi。我不得不稍微重构你的代码,但它做到了我需要的。我曾希望有一种更干净的方法来做到这一点,但这肯定比我所拥有的要好。是的,如果下划线e确实提供了一个对对象有效的
map
。然后我们可以做
b=map(数字,(x)->x-5);a=map(b,(x)->max(x,0));ratio=sum(b)/sum(a);adjusted=map(a,(x)->x*ratio+5)
谢谢。
map
的有趣用法。
var numbers = {…},
    adjusted = {};

var min = 5,
    sum = 0,
    count = 0,
    below = 0,
    belowCount = 0;
_.each(numbers, function(k, num) {
    sum += num;
    count++;
    if (num < min) {
        below += num;
        belowCount++;
    }
});
var aim = sum - min * count;
if (aim < 0)
    throw "Too many values, giving every the minimum would exceed sum";
var overMin = sum - below - (count-belowCount) * min,
    ratio = aim / overMin;
_.each(numbers, function(key, num) {
    if (num <= min)
        adjusted[key] = min;
    else
        adjusted[key] = min + (num - min) * ratio;
});