以“蛇形”顺序合并两个数组

时间:2019-03-07 16:05:46

标签: javascript arrays

我对这项任务的解决方案感到困惑。我有两个数组:

const arr1 = [ 1,   2,   3,   4, 5, 6, 7, 8];
const arr2 = ['a', 'b', 'c', 'd'];

合并这些数组后我想得到什么:

[1, 'a', 'b', 2, 3, 'c', 'd', 4, 5, 6, 7, 8];

从图形上看它像蛇一样

image

在第一个数组的长度小于第二个数组的长度的情况下,它也必须起作用。例如,我有两个数组:

const arr1 = [ 1,   2,   3,   4];
const arr2 = ['a', 'b', 'c', 'd', 'e', 'f', 'g'];

我想在合并后得到:

[1, 'a', 'b', 2, 3, 'c', 'd', 4, 'e', 'f', 'g'];

(image)

5 个答案:

答案 0 :(得分:1)

function reorderArrays(array1, array2){
  let newArray = [];
  
  while(array1.length || array2.length) {
      array1.length && newArray.push(array1.shift());
      array2.length && newArray.push(array2.shift());
      array2.length && newArray.push(array2.shift());
      array1.length && newArray.push(array1.shift());
  }
  return newArray;
}

console.log(reorderArrays([1, 2, 3, 4, 5, 6, 7, 8], ['a', 'b', 'c', 'd']));
console.log(reorderArrays([ 1,   2,   3,   4], ['a', 'b', 'c', 'd', 'e', 'f', 'g']));

还有优化的余地(例如,如果一个数组的长度为!length,只需将另一个数组的其余部分推到新数组中即可)

此解决方案适用于未定义的边缘情况。

答案 1 :(得分:1)

这是一种简短而不变的方法:

const snake = (a, b) => Array.from( // create an array
    { length: Math.max(a.length, b.length) }, // as long as the longest of a and b
    (_, i) => i % 2 ? [b[i], a[i]] : [a[i], b[i]] // fill it with alternating pairs from a and b
  ).flat().filter(x => x !== undefined); // then flatten the pairs and remove undefined entries

console.log(...snake([1, 2, 3, 4, 5, 6, 7, 8], ['a', 'b', 'c', 'd']));
console.log(...snake([1, 2, 3, 4], ['a', 'b', 'c', 'd', 'e', 'f', 'g']));
console.log(...snake([1, 2, 4, 5], []));
console.log(...snake([], ['a', 'b', 'c', 'd']));

步骤是:

  1. 使用Array.from()
  2. 创建最长的数组
  3. 用您的第一个数组填充它,如果较短,则其余的将用undefined填充
  4. 使用Array.from()的第二个参数或使用map()将条目转换成两个数组中的对,并通过检查索引是偶数还是奇数来改变对的顺序
  5. 使用Array.flat()拼合结果
  6. 使用Array.filter()过滤掉undefined

答案 2 :(得分:0)

这是使用flatMap的一种解决方案:

const merge = (arr1, arr2) => {
  return arr1.flatMap((x, i) => {
    const items = [x];
    if (i % 2 === 0) {
      if (i < arr2.length) {
        items.push(arr2[i]);
      }
      if (i + 1 < arr2.length) {
        items.push(arr2[i + 1]);
      }
    }
    if (i + 1 === arr1.length) {
      items.push(...arr2.slice(i + 1));
    }
    return items;
  });
}

console.log(merge([1, 2, 3, 4, 5, 6, 7, 8], ['a', 'b', 'c', 'd']));    // [1, "a", "b", 2, 3, "c", "d", 4, 5, 6, 7, 8]

console.log(merge([1, 2, 3, 4], ['a', 'b', 'c', 'd', 'e', 'f', 'g'])); // [1, "a", "b", 2, 3, "c", "d", 4, "e", "f", "g"]

说明:

您传递给flatMap的函数将按顺序返回要包含在结果数组中的元素数组。该数组是通过以下方式循环flatMap来确定的:

  1. 每个元素都直接包含在结果([x]
  2. 对于每个偶数索引(i % 2 === 0),从arr2.push(arr2[i]).push(arr2[i + 1]))中插入最多两个元素。
  3. 如果您位于arr1i + 1 === arr1.length)的末尾,请插入arr2.push(...arr2.slice(i + 1)))中的所有剩余项

答案 3 :(得分:0)

在这里,您基于对所需内容的了解而采用了递归方法:

  

形成第一个数组:取1个项目,然后取2个项目,然后取1个项目,再取2个项目,依此类推。从第二个数组中总是取出2个项目。

为概括起见,该方法将收到两个额外的数组,这些数组将确定要合并的每个数组中要获取的元素的周期:

const customMerge = (a, b, toTakeA=[1], toTakeB=[1], res=[], i=0, j=0) =>
{
    if (!a.length)
        return res.concat(b);
    else if (!b.length)
        return res.concat(a);

    return customMerge(
        a.slice(toTakeA[i]),
        b.slice(toTakeB[j]),
        toTakeA,
        toTakeB,
        res.concat(a.slice(0, toTakeA[i])).concat(b.slice(0, toTakeB[j])),
        i >= toTakeA.length - 1 ? 0 : i + 1,
        j >= toTakeB.length - 1 ? 0 : j + 1
    );
}

console.log("First OP merge: ", customMerge(
    [1, 2, 3, 4, 5, 6, 7, 8],
    ['a', 'b', 'c', 'd'],
    [1, 2],
    [2]
));

console.log("Second OP merge: ", customMerge(
    [1, 2, 3, 4],
    ['a', 'b', 'c', 'd', 'e', 'f', 'g'],
    [1, 2],
    [2]
));

// Another custom merge.
console.log("A custom merge: ", customMerge(
    [1, 2, 3, 4, 5, 6, 7, 8, 9],
    ['a', 'b', 'c', 'd', 'e', 'f', 'g'],
    [1, 1, 2],
    [2, 1]
));

// Simple merge, 1 and 1.
console.log("Single 1 and 1 merge: ", customMerge(
    [1, 2, 3, 4, 5, 6, 7, 8, 9],
    ['a', 'b', 'c', 'd', 'e', 'f', 'g']
));
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}

如果您需要阅读有关它们的文档,该方法主要使用Array.slice()Array.concat()

答案 4 :(得分:0)

您可以先获取一个偏移量和第一个数组的多余元素,然后再从两个数组中获取两个元素。这种方法不会改变原始数组。

function getSnaked(a, b) {
    var result = [],
        l = Math.min(a.length, b.length),
        i = 0;

    result.push(...a.slice(0, 1));
    while (i < l) {
        result.push(...b.slice(i, ++i + 1));
        result.push(...a.slice(i, ++i + 1));
    }
    result.push(...b.slice(i));
    result.push(...a.slice(i + 1));
    return result;
}

console.log(...getSnaked([1, 2, 3, 4], ['a', 'b', 'c', 'd', 'e', 'f', 'g']));
console.log(...getSnaked([1, 2, 3, 4, 5, 6, 7, 8], ['a', 'b', 'c']));
console.log(...getSnaked([1, 2, 3, 4], []));
console.log(...getSnaked([], ['a', 'b', 'c', 'd', 'e', 'f', 'g']));