(upper+lower)/2 怎么样?
扩展@msander 的答案,您可以使用字母数字优先级来确保您始终拥有“中间”优先级来分配。如果你需要分配许多优先级,两个连续优先级之间的距离会越来越小,最终会失去精度,你会得到类似 ((upper + lower)/2 === lower) 的东西。
如果您更改获得中间优先级的方式,则可以使用字符串(不损失精度)而不是实际数字。例如,如果您的优先级是类似字符串的数字(由 0、1、2、3、4、5、6、7、8、9 组成的字符串):
['1', '3', '4']
在 1 和 3 之间移动 4 将导致:['1', '2', '3']
在 2 和 1 之间移动 3 将导致:['1', '15', '2']
在 1 和 15 之间移动 2 将导致:['1', '12', '15']
您需要注意的是如何比较优先级(String.prototype.localeCompare)。
同样,只有当您预计会遇到精度损失问题时,此解决方案才值得麻烦。
编辑(添加了一个计算优先级的函数):
免责声明:该代码出乎意料地难以理解。如果有人有更好的想法,请随意加入。如果您只使用二进制字符串(仅包含 0 和 1 的字符串),编写起来会容易得多。
function getMiddlePriority(p1, p2) {
var i=0,result = '';
// The identical digits need to be in the result
while ((p1[i] || '0') === (p2[i] || '0')) {
result += p1[i++] || '0';
}
// First different digit p1[i] !== p2[i]
// if the digits are far enough apart, there is a number between them
if ((p2[i]||0) - (p1[i]||0) > 1) {
return result + Math.floor(((+p2[i]||0) + (+p1[i]||0))/2);
}
// p2[i] === p1[i]+1
// Digits are close, need to parse some more digits to get a number between
var first = i++;
var k = 0;
while ((p1[i] === '9') && ((p2[i]||'0') === '0')) {
i++;
k++;
}
// p[i] is not 9 or p2[i] is not 0/undefined
if (p1[i] === '9') {
result += (p2[first]||'0') + repeat('0', k);
result += p2[i] === '1' ? '05' : Math.floor(p2[i]/2);
} else {
result += (p1[first]||'0') + repeat('9', k);
result += Math.floor((10 + (+p1[i] || 0))/2);
}
return result;
}
function repeat(character, count) {
var s = '';
while (count--) s+= character;
return s;
}
console.clear();
console.log('Expected 2 Got ' + getMiddlePriority('1', '3'));
console.log('Expected 25 Got ' + getMiddlePriority('2', '3'));
console.log('Expected 22 Got ' + getMiddlePriority('2', '25'));
console.log('Expected 21 Got ' + getMiddlePriority('2', '22'));
console.log('Expected 205 Got ' + getMiddlePriority('2', '21'));
console.log('Expected 202 Got ' + getMiddlePriority('2', '205'));
console.log('Expected 215 Got ' + getMiddlePriority('21', '22'));
console.log('Expected 1055 Got ' + getMiddlePriority('105', '106'));
console.log('Expected 10995 Got ' + getMiddlePriority('1099', '11'));
console.log('Expected 1105 Got ' + getMiddlePriority('1099', '111'));
字符串优先级的替代方法是使用数字优先级,并且每隔一段时间(何时(upper+lower)/2 === lower || (upper+lower)/2 === upper
)重新分配优先级。当然这不适合这个问题,因为对于 N 次重新排序,您不会进行 1 次更新,而是进行1+ N/S
更新,其中 S 是您在用完可用优先级之前可以进行的更新量。至少这是一个正确的解决方案(优先级总是唯一的)。