我希望我能早点找到这个。无论如何,在现代 JS 中,可以(并且希望!)在没有条件的情况下做到这一点,并且有一个优雅的算法可以通过使用占位符来实现这一点。
具体来说,我们可以使用 aSymbol
作为在有序集中移动的元素的替代。这样,索引算术就被消除了(并且随之而来的是大量的条件和地方错误恶化的地方)。
工作原理基本上是这样的:
withGroupRepositioned(["a", "b", "c", "d"], ["a", "b"], 0) // [ 'a', 'b', 'c', 'd' ]
withGroupRepositioned(["a", "b", "c", "d"], ["a", "b"], 1) // [ 'a', 'b', 'c', 'd' ]
withGroupRepositioned(["a", "b", "c", "d"], ["a", "b"], 2) // [ 'a', 'b', 'c', 'd' ]
withGroupRepositioned(["a", "b", "c", "d"], ["a", "b"], 3) // [ 'c', 'a', 'b', 'd' ]
withGroupRepositioned(["a", "b", "c", "d"], ["b", "a"], 2) // [ 'b', 'a', 'c', 'd' ]
withGroupRepositioned(["a", "b", "c", "d"], ["b", "a"], 3) // [ 'c', 'b', 'a', 'd' ]
withGroupRepositioned(["a", "b", "c", "d"], ["a", "c"], 4) // [ 'b', 'd', 'a', 'c' ]
整个功能是:
const PLACEHOLDER = Symbol();
function withGroupRepositioned(inOrderedSet, valuesToReposition, toIndex) {
// Do not damage the given set
const cpy = [].concat(inOrderedSet);
// Step 1. Replace all traveling elements with placeholders, in place.
valuesToReposition.forEach((v) => cpy[cpy.indexOf(v)] = PLACEHOLDER);
// Step 2. Reinsert values as a group, where we want them.
cpy.splice(toIndex, 0, ...valuesToReposition);
// Step 3. Remove placeholders.
return cpy.filter((v) => v !== PLACEHOLDER);
}
如果要就地执行重新排列,可以删除第一个数组复制操作。