0

合計が 100% を超えてはならない値として数字だけを持つオブジェクトがあります。ただし、各数値には最小量 (5% としましょう) が必要です。これは基本的に、配列内の数値が 0 の場合、5% に設定され、その金額が 0 より大きい他のすべての数値に分配されることを意味します。

明らかに、問題の 1 つは、数値がもともと 6% だったのに、実際には最小値を下回る状況につながる可能性があることです。

現在、私の解決策はこれです(Underscoreを使用):

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 に答える