给定一个这样的数组:
var buckets = [
{name: "bucket1", value: 10000},
{name: "bucket2", value: -5000},
{name: "bucket3", value: -2000},
]
我试图将负数"归零"。在给定的每种情况下,所有值加在一起的总和永远不会是负数。我所说的"零出"是指取任何正数,然后按照它们出现的顺序将它们减以负数。
因此,如果第一个数字和第三个数字为负数,而第二个数字为正数,它将减少第二个数字的第一个,然后减少第三个数字。
之后我的示例的结束值分别为 3000、0、0。
这些数字可以以任意组合和顺序出现,只要它们的总和都是正数。
这不是最好的解决方案,但这样的东西应该有效。
伪代码:
// for every item in the bucket
for(var i = 0; i < buckets.length; i++){
// if the value of this bucket is negative
if(buckets[i].value < 0) {
// look through every bucket again
for(var j = 0; j < buckets.length; j++) {
// and if we find one that is positive
if(buckets[j].value > 0) {
// add all the positive to this negative
buckets[i].value += buckets[j].value;
// if it's still negative we are gonna start again
if(buckets[i].value < 0) {
i--;
break;
}
}
}
}
}
您可以对数组执行reduce
,并按正/负值分隔存储桶。 然后迭代负数,将每个负数减少一个正数,直到它达到零并根据需要移动到下一个负数。
var buckets=[{name:"bucket1",value:1e4},{name:"bucket2",value:-5e3},{name:"bucket3",value:-2e3}],
result = buckets.reduce( ( a, v, i, {
length
} ) => {
let isNeg = Math.sign( v.value ) == -1;
isNeg ? a.n.push( v ) : a.p.push( v );
if ( i < length - 1 ) {
return a;
} else {
return [ ...a.n.map( n => {
while ( n.value < 0 ) {
let pos = a.p.find( ( {
value
} ) => value > 0 ),
tval = n.value + pos.value,
nval, posval;
if ( tval >= 0 ) {
nval = 0;
posval = tval;
} else {
nval = tval;
posval = pos.value + n.value;
}
pos.value = posval;
n.value = nval;
}
return n;
} ), ...a.p ]
}
}, {
p: [],
n: []
} );
console.log( result );