前端实现排序数组的合并
数组的排序与合并都是极为常见的操作。其中,排序的实现有着非常多的现成代码,这里就不再赘述了;对于无序数组的合并与排序,可以先合并,再排序。
这里要分享的则是前端实现将两个升序数组合并成一个升序数组,并支持自定义数组元素的比较函数,以及是否需要对相同元素进行去重。
export function mergeSortedArray<T = any>(
array1: T[],
array2: T[],
compare?: {
// 自定义前者是否小于后者的判断函数,默认为小于操作符
less?: (value1: T, value2: T) => boolean,
// 自定义去重的判断函数,默认为undefined,即不去重
same?: (value1: T, value2: T) => boolean,
}
) {
if (!array1.length) {
return array2;
}
if (!array2.length) {
return array1;
}
const less = compare?.less || ((value1: T, value2: T) => value1 < value2);
if (less(array1.at(-1)!, array2[0])) {
// 如果array1最后一个元素比array2第一个元素小,直接拼接
return array1.concat(array2);
}
if (less(array2.at(-1)!, array1[0])) {
// 如果array2最后一个元素比array1第一个元素小,直接拼接
return array2.concat(array1);
}
const same = compare?.same;
let a1 = array1;
let a2 = array2;
let i1 = 0, i2 = 0;
let arrayMerged: T[] = [];
while (true) {
while (less(a1[i1], a2[i2])) {
arrayMerged.push(a1[i1]);
i1++;
if (i1 == a1.length) {
arrayMerged.push(...a2.slice(i2));
return arrayMerged;
}
}
// 如果定义了compare.same,将判读是否相同元素并去重
if (same && same(a1[i1], a2[i2])) {
i1++;
if (i1 == a1.length) {
arrayMerged.push(...a2.slice(i2));
return arrayMerged;
}
}
arrayMerged.push(a2[i2]);
i2++;
if (i2 == a2.length) {
arrayMerged.push(...a1.slice(i1));
return arrayMerged;
}
let a = a2;
a2 = a1;
a1 = a;
let i = i2;
i2 = i1;
i1 = i;
}
}
其实,还可以写成递归函数,代码看起来会优雅一些。对于数据量不大的数组来说,性能上带来的延迟影响也并不会很明显。