【问题标题】:Redistribute a range of percentages according to a minimum value, while keeping relative proportions根据最小值重新分配百分比范围,同时保持相对比例
【发布时间】:2013-08-16 19:31:58
【问题描述】:

在这里提琴:http://jsfiddle.net/jakelauer/5S8t8/

我需要做什么

循环遍历一个百分比范围,加起来等于 100%,并将低于最小阈值的任何值设置为某个百分比,然后重新分配剩余的百分比,使它们彼此之间仍然相同,所以整个范围仍然等于 100%。

为什么?

我正在制作一个饼图,我需要在饼图上显示每个值,即使它是零值,以便它仍然可以点击。这意味着我需要将低于某个阈值的值设置为更高的值,但我不想失去更高值的相对比例,它们不能超过 100%

详情

假设我有一个值范围:

var range = [190, 2453, 234, 14, 1244, 532, 0, 3, 1999];

然后我将它们转换为百分比值,这样范围内的每个值都成为其在整个范围总和中的百分比,结果是:

[0.02849002849002849, 0.36782126255810466, 0.03508771929824561, 0.002099265257159994, 0.18653471285050233, 0.07977207977207977, 0, 0.000449842555105713, 0.2997450892187734]

我想遍历这些百分比并将它们设置为最小值0.02,即 2%。这是我到目前为止的代码:

var range = [190, 2453, 234, 14, 1244, 532, 0, 3, 1999];
var minimumPercent = 0.02;

function distributeRangeGivenMinimum(range, min) {
    var sum = 0;
    for (var i = 0; i < range.length; i++) {
        sum += range[i];
    }

    var percents = [];
    for (var i = 0; i < range.length; i++) {
        percents.push(range[i] / sum);
    }

    var amtToSubtract = 0;
    var timesUnderMin = 0;
    for (var i = 0; i < range.length; i++) {
        if (percents[i] < min) {
            amtToSubtract += (min - percents[i]);
            timesUnderMin++;
            percents[i] = min;
        }
    }

    var timesOverMin = percents.length - timesUnderMin;
    if (timesOverMin > 0) {
        for (var i = 0; i < range.length; i++) {
            if (percents[i] > min) {
                percents[i] = percents[i] - (amtToSubtract / timesOverMin);
            }
        }
    }

    return percents;
}

上述函数的问题在于,虽然它确实完成了重新分配,但如果任何值刚好高于最小值(例如,如果其中一个值是 0.0201 和最小值是 0.02 或其他值),它们在重新分配后最终低于最小值,我不知道如何解决。

【问题讨论】:

  • 你说的上面是什么意思?
  • 我的意思是勉强超过最低限度。例如,如果某个百分比最终为 0.021,而最小值为 0.02,则在重新分配后它可能最终会低于最小值。
  • 您可以迭代直到没有更多的值低于最小值。在每次迭代中,找到最小值以下的值,将它们向上提升,找到最小值以上的值,然后将它们从 100% 中取出所有最小值后的剩余值重新缩放。如果您将列表分为两个列表:下方和上方,可能会更容易。

标签: javascript arrays algorithm percentage


【解决方案1】:

尝试以下(新部分由 cmets 标记):

var range = [190, 2453, 234, 14, 1244, 532, 0, 3, 1999];
var minimumPercent = 0.02;

function distributeRangeGivenMinimum(range, min) {
    var sum = 0;
    for (var i = 0; i < range.length; i++) {
        sum += range[i];
    }

    var percents = [];
    for (var i = 0; i < range.length; i++) {
        percents.push(range[i] / sum);
    }

    var amtToSubtract = 0;
    var timesUnderMin = 0;
    for (var i = 0; i < range.length; i++) {
        if (percents[i] < min) {
            amtToSubtract += (min - percents[i]);
            timesUnderMin++;
            percents[i] = min;
        }
    }

    var timesOverMin = percents.length - timesUnderMin;
    // begin new section
    do {
        var prevTimesOverMin = timesOverMin;
        var distSubAmt = amtToSubtract / timesOverMin;
        for (var i = 0; i < range.length; i++) {
            if (percents[i] > min && percents[i] - distSubAmt < min) {
                amtToSubtract -= (percents[i] - min);
                timesOverMin--;
                percents[i] = min;
            }
        }
    } while (timesOverMin != prevTimesOverMin);
    // end new section

    if (timesOverMin > 0) {
        for (var i = 0; i < range.length; i++) {
            if (percents[i] > min) {
                percents[i] = percents[i] - (amtToSubtract / timesOverMin);
            }
        }
    }

    return percents;
}

【讨论】:

    猜你喜欢
    • 2021-08-23
    • 2021-02-16
    • 1970-01-01
    • 2012-06-10
    • 2021-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多