合并两个具有交替值的数组

IT技术 javascript ecmascript-6 functional-programming
2021-01-13 21:35:25

我想合并 2 个不同长度的数组:

let array1 = ["a", "b", "c", "d"];
let array2 = [1, 2];

我期望的结果是 ["a", 1 ,"b", 2, "c", "d"]

最好的方法是什么?

6个回答

这是使用解构赋值的另一种方法 -

const interleave = ([ x, ...xs ], ys = []) =>
  x === undefined
    ? ys                             // base: no x
    : [ x, ...interleave (ys, xs) ]  // inductive: some x
        
console.log (interleave ([0, 2, 4, 6], [1, 3, 5])) // [ 0 1 2 3 4 5 6 ]    
console.log (interleave ([0, 2, 4], [1, 3, 5, 7])) // [ 0 1 2 3 4 5 7 ]
console.log (interleave ([0, 2, 4], []))           // [ 0 2 4 ]
console.log (interleave ([], [1, 3, 5, 7]))        // [ 1 3 5 7 ]
console.log (interleave ([], []))                  // [ ]

另一个支持任意数量输入数组的变体 -

const interleave = ([ x, ...xs ], ...rest) =>
  x === undefined
    ? rest.length === 0
      ? []                               // base: no x, no rest
      : interleave (...rest)             // inductive: no x, some rest
    : [ x, ...interleave(...rest, xs) ]  // inductive: some x, some rest

console.log (interleave ([0, 2, 4, 6], [1, 3, 5])) // [ 0 1 2 3 4 5 6 ]    
console.log (interleave ([0, 2, 4], [1, 3, 5, 7])) // [ 0 1 2 3 4 5 7 ]
console.log (interleave ([0, 2, 4], []))           // [ 0 2 4 ]
console.log (interleave ([], [1, 3, 5, 7]))        // [ 1 3 5 7 ]
console.log (interleave ([], []))                  // [ ]

您可以迭代两个数组的最小长度并构建替代元素,最后推送其余元素。

var array1 = ["a", "b", "c", "d"],
    array2 = [1, 2],
    result = [],
    i, l = Math.min(array1.length, array2.length);
    
for (i = 0; i < l; i++) {
    result.push(array1[i], array2[i]);
}
result.push(...array1.slice(l), ...array2.slice(l));

console.log(result);

使用转置算法和后来的展平解决任意数量的数组。

var array1 = ["a", "b", "c", "d"],
    array2 = [1, 2],
    result = [array1, array2]
        .reduce((r, a) => (a.forEach((a, i) => (r[i] = r[i] || []).push(a)), r), [])
        .reduce((a, b) => a.concat(b));
    
console.log(result);

创建一个元组数组。每个元组包含来自每个数组的 1 个元素,通过展开元组数组并添加数组中的剩余项来展平:

const a1 = ["a", "b", "c", "d"];
const a2 = [1,2];
const l = Math.min(a1.length, a2.length);

const merged = [].concat(...Array.from({ length: l }, (_, i) => [a1[i], a2[i]]), a1.slice(l), a2.slice(l));
  
console.log(merged);

Array.from() 和 .filter() 需要 4.044921875ms 而 result.push() 需要 3.296630859375ms
2021-04-07 21:35:25

这是一个采用任意数量数组的现代解决方案:

const braidArrays = (...arrays) => {
  const braided = [];
  for (let i = 0; i < Math.max(...arrays.map(a => a.length)); i++) {
    arrays.forEach((array) => {
      if (array[i] !== undefined) braided.push(array[i]);
    });
  }
  return braided;
};

请注意,您可以更改Math.maxMath.min仅包含最短的数组。

这是一个示例 I/O:

braidArrays(['a','b','c','d'], [1,2,3], [99,98,97,96,95]);
// ['a', 1, 99, 'b', 2, 98, 'c', 3, 97, 'd', 96, 95]

ONELINER:我假设x=array1, y=array2, x 和 y 可以是任意的 arr

[...x,...y].reduce((l,c,i)=>(i<x.length&&l.push(x[i]),i<y.length&&l.push(y[i]),l),[])

工作示例(3个案例)