我有一个
target
数组,说:[A, C, E, F, H]
。
我有另一个数组 toMerge
需要合并到 target
中,比如:[B, D, G, I]
。
我还有一个整数数组,它告诉目标数组的索引,其中 toMerge
项最终将合并到,例如:[1, 3, 6, 8]
。
我需要一个函数,将
toMerge
数组合并到 target
中,在 indices
数组指定的索引处,以便 target
最终看起来像
[A(0), B(1), C(2), D(3), E(4), F(5), G(6), H(7), I(8)]
我尝试使用内置的数组拼接函数来迭代索引数组并在每个索引处进行拼接(添加)。大致意思是:
for (let i = 0; i < indices.length; i++) {
target.splice(indices[i], 0, toMerge[i]);
}
我正在寻找任何可以更高效、更优雅地完成此操作的解决方案。
如果
indices
数组是未排序或更糟 - 反向排序,事情会变得更加棘手!例如,
toMerge: [I, G, D, B]
indices: [8, 6, 3, 1]
应用上述算法后,
target
最终为:
target: [A, B, C, E, D, F, H, I, G]
解决此问题的一种方法是将
indices
数组与 toMerge
数组一起按非降序排序,以确保遵循顺序,但这会使事情进一步复杂化。
如果您正在使用未排序的索引:您必须“压缩”(需要首先
transpose
)要合并的数组及其相应的索引。一旦您对 [index, value][]
矩阵进行了排序,就可以执行有序拼接。
const transpose = (a) => a[0].map((_, i) => a.map(r => r[i]));
const sortByIndex = (a) => a.sort((x, y) => x[0] - y[0]);
const absoluteMerge = (a, toMerge, unsortedIndices) => {
const res = [...a];
const sorted = sortByIndex(transpose([unsortedIndices, toMerge]));
for (let i = 0; i < sorted.length; i++) {
res.splice(sorted[i][0], 0, sorted[i][1]);
}
return res;
};
const a = ['A', 'C', 'E', 'F', 'H'], b = ['I', 'G', 'D', 'B'];
const c = absoluteMerge(a, b, [8, 6, 3, 1]);
console.log(...c); // A B C D E F G H I
如果您正在使用绝对索引(就像您一样),您可以按顺序插入项目;但如果使用相对索引,则需要反转插入。
const absoluteMerge = (a, b, insertionIndices) => {
const res = [...a];
for (let i = 0; i < insertionIndices.length; i++) {
res.splice(insertionIndices[i], 0, b[i]);
}
return res;
};
const a = ['A', 'C', 'E', 'F', 'H'], b = ['B', 'D', 'G'];
const c = absoluteMerge(a, b, [1, 3, 6]);
console.log(...c); // A B C D E F G H
const relativeMerge = (a, b, insertionIndices) => {
const res = [...a];
for (let i = insertionIndices.length - 1; i >= 0; i--) {
res.splice(insertionIndices[i], 0, b[i]);
}
return res;
};
const a = ['A', 'C', 'E', 'F', 'H'], b = ['B', 'D', 'G'];
const c = relativeMerge(a, b, [1, 2, 4]);
console.log(...c); // A B C D E F G H
考虑排序、逆序和未排序列表的可能性
toMerge
,首先我们需要将toMerge
与indices
列表合并并排序,然后我们可以将这些值与target
列表合并,例如:
const mergeArraysByIndex = (target, toMerge, indices) => {
// Create an array of objects with keys and values
const toMergeWithIndex = toMerge.map((key, index) => ({key, value: indices[index]}));
// Sort the array of objects by value
toMergeWithIndex.sort((a, b) => a.value - b.value);
// Create a final object with sorted keys and values
const resultObject = {};
toMergeWithIndex.forEach(item => {
resultObject[item.key] = item.value;
});
//Merge the arrays together
return Object.values(resultObject).reduce((acc, index, i) => {
acc.splice(index, 0, Object.keys(resultObject)[i]);
return acc;
}, [...target])
}
//First example (sorted!)
console.log(mergeArraysByIndex(['A', 'C', 'E', 'F', 'H'], ['B', 'D', 'G'], [1, 3, 6]));
//Second example (reverse-sorted!)
console.log(mergeArraysByIndex(['A', 'C', 'E', 'F', 'H'], ['I', 'G', 'D', 'B'], [8, 6, 3, 1]));
//Third example (unsorted!)
console.log(mergeArraysByIndex(['A', 'C', 'E', 'F', 'H'], ['D', 'I', 'G', 'B'], [3, 8, 6, 1]));
或者以恢复的方式:
const mergeArraysByIndex = (target, toMerge, indices) => {
return indices
.map((index, i) => ({ key: toMerge[i], index }))
.sort((a, b) => a.index - b.index)
.reduce((acc, { key, index }) => {
acc.splice(index, 0, key);
return acc;
}, [...target]);
};
//First example (sorted!)
console.log(mergeArraysByIndex(['A', 'C', 'E', 'F', 'H'], ['B', 'D', 'G'], [1, 3, 6]));
//Second example (reverse-sorted!)
console.log(mergeArraysByIndex(['A', 'C', 'E', 'F', 'H'], ['I', 'G', 'D', 'B'], [8, 6, 3, 1]));
//Third example (unsorted!)
console.log(mergeArraysByIndex(['A', 'C', 'E', 'F', 'H'], ['D', 'I', 'G', 'B'], [3, 8, 6, 1]));