0

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

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

目前,我的解决方案是这样的(使用下划线):

var numbers         = //this is the object,
    adjustedNumbers = {},
    // _.objFilter here is just like _.filter, but returns an object instead
    // of an array, retaining the key-value pairs
    zeroValues      = _.objFilter(numbers, function(num){ return num == 0 });
    greaterThanTen  = _.objFilter(numbers, function(num){ return num >= 10 });

    _.each(greaterThanTen, function(ratio, key){
        adjustedRangeRatio[key] = ratio - (_.size(zeroValues) / _.size(greaterThanTen)) * 5;
    });

    _.each(zeroValues, function(value, key){
          zeroValues[key] = 5;
    }

    _.extend(adjustedRangeRatio, zeroValues);

这行得通,但是,它非常丑陋。我确信有一种更好、更清洁、更可扩展的方法来做到这一点。

4

1 回答 1

0

一个数字最初是 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;
});
于 2013-09-18T11:30:19.603 回答