简体   繁体   English

以“压缩”方式组合两个数组-JavaScript

[英]Combine two arrays in a “zipping” fashion - JavaScript

So, I've been thinking of just some little practice things that I could do with arrays in JavaScript. 因此,我一直在思考可以使用JavaScript数组进行的一些小练习。 I came across the idea of combining two arrays in a "zipping" fashion (arrayA[0], arrayB[0], arrayA[1], arrayB[1]...) and so on and so forth. 我遇到了以“压缩”方式组合两个数组的想法(arrayA[0], arrayB[0], arrayA[1], arrayB[1]...) ,依此类推。 Anything left over in a potential longer array would be tacked onto the end. 可能更长的阵列中剩下的任何东西都将固定在末端。

I've searched stackoverflow - reason I'm asking is I'm currently in introductory programming courses, so we don't really know a whole lot of "things" we can do with JavaScript. 我已经搜索了stackoverflow-我要问的原因是我目前正在参加编程入门课程,因此我们并不真正了解使用JavaScript可以完成的很多“工作”。 Would like to see a solution with "simple" methods if possible! 如果可能的话,希望看到使用“简单”方法的解决方案!

I've currently got the alternate fashion going, but I can't seem to get the last part of tacking the remaining parts of the array to the very end. 目前,我已经有了另一种流行的方式,但是我似乎还没掌握将数组其余部分固定到最后的最后一部分。

function alternatingMerge(array1, array2)
//this function will merge two different arrays in an alternating fashion
//i.e = array1[0], array2[0], array1[1], array2[1], array1[2], array2[2], ... , etc
{
    var mergedArray;
    var i; // while loop counter
    var j; // 
    var k; // 
    var arrayLengths;

    arrayLengths = array1.length + array2.length;
    i = 0; // 
    j = 0; // ARRAY1 COUNTER
    k = 0; // ARRAY2 COUNTER
    mergedArray = new Array(arrayLengths);
    //window.alert(mergedArray);

    while (i < arrayLengths)
    {
        if (i%2 === 0)
        {
            mergedArray[i] = array2[j];
            j = j + 1;
        }
        else
        {
            mergedArray[i] = array1[k];
            k = k + 1;
        }
        i = i + 1;
    }
    return mergedArray;
}

I feel like it's simple stuff but some help would be appreciated! 我觉得这很简单,但是可以得到一些帮助!

Here is a small but effective weaving function for two arrays of any size using ES6 (modern browsers): 这是使用ES6(现代浏览器)对任意大小的两个数组的一个很小但有效的编织函数:

 var w = (a, b) => a.length ? [a[0], ...w(b, a.slice(1))] : b; var array1 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; var array2 = ['A', 'B', 'C', 'D', 'E']; console.log(JSON.stringify(w(array1, array2))); 

Explanation: 说明:

The variable w is set to this short recursive function: 变量w设置为此简短的递归函数:

(a, b) => a.length ? [a[0], ...w(b, a.slice(1))] : b

I'll explain it piece by piece since there's no room for comments. 由于没有评论的余地,我将逐一解释。

(a, b) => - For two input arrays, a and b . (a, b) => -对于两个输入数组, ab

a.length - Check if the first array is not empty. a.length检查第一个数组是否不为空。

? [___] ? [___] - If it is not empty, return an array. ? [___] -如果不为空,则返回一个数组。

a[0], - Make the first item in this array the same first item from the first array. a[0], -使该数组中的第一项与第一个数组中的第一项相同。

...w(b, a.slice(1)) - Fill the rest of the array with the results of this same function using array b for the first parameter and everything but the first item of array a for the second parameter. ...w(b, a.slice(1)) -使用数组b作为第一个参数,除数组a的第一项以外的所有内容作为第二个参数,用同一函数的结果填充数组的其余部分。

: b - Otherwise, if the first array is empty, return array b . : b否则,如果第一个数组为空,则返回数组b

What it ends up doing is switching between the first and second arrays, removing the first item from that array and passing it back recursively to the result array. 它最终要做的是在第一和第二数组之间切换,从该数组中删除第一项,然后将其递归传递回结果数组。 It does this until one of the arrays has no items left, at which point the rest of the other array is returned and added to the end of the result. 它会这样做,直到其中一个数组没有剩余的项目为止,这时将返回另一个数组的其余部分,并将其添加到结果的末尾。


With a few adjustments, it can rotate through any number of arrays. 通过一些调整,它可以旋转任意数量的阵列。 This version runs basically the same way, except the first array gets a default value to handle no arguments being fed in, and the second parameter handles multiple arrays instead of one. 此版本的运行方式基本相同,除了第一个数组获取默认值以处理没有输入的参数,第二个参数处理多个数组而不是一个。 Also, before checking the length of array a , it counts the arrays in b to see if there are any arrays left to rotate through. 同样,在检查数组a的长度之前,它将对b的数组进行计数,以查看是否还有剩余的数组可以旋转。 If there aren't any, array a is returned. 如果没有,则返回数组a If there are arrays left, but a is empty, the results of the recursive function are returned using the remaining arrays as its parameters. 如果还剩数组,但a为空,则使用剩余数组作为参数返回递归函数的结果。

 var w = (a = [], ...b) => b.length ? a.length ? [a[0], ...w(...b, a.slice(1))] : w(...b) : a; var array1 = [1, 2]; var array2 = '♦♡♣♤♥♢'; var array3 = ['A', 'B', 'C']; var array4 = ['😊', '😔', '😠']; var array5 = [null, NaN, undefined]; var stringify = (o) => JSON.stringify(o, (k, v) => v === undefined ? '__undefined__' : v !== v ? '__NaN__' : v).replace(/"__undefined__"/g, 'undefined').replace(/"__NaN__"/g, 'NaN'); console.log(stringify(w())); console.log(stringify(w(array1))); console.log(stringify(w(array1, array2))); console.log(stringify(w(array1, array2, array3))); console.log(stringify(w(array1, array2, array3, array4))); console.log(stringify(w(array1, array2, array3, array4, array5))); 

The stringify function is something I added to correct for JSON.stringify converting NaN and undefined into null . 我添加了stringify函数以更正JSON.stringifyNaNundefined转换为null It does not effect the way the weaving function works. 它不会影响编织功能的工作方式。

How about this: 这个怎么样:

function mergeAlternating(array1, array2) {
    var mergedArray = [];

    for (var i = 0, len = Math.max(array1.length, array2.length); i < len; i++) {
        if (i < array1.length) {
            mergedArray.push(array1[i]);
        }
        if (i < array2.length) {
            mergedArray.push(array2[i]);
        }
    }
    return mergedArray;
}

Here's a quick take... 快速采取...

// Takes an arbitrary number of arrays as arguments
function zip() {
   var merged = [], index = 0, cont, i;
   do {
      cont = false;
      for (var i=0; i<arguments.length; i++) {
         A = arguments[i];
         if (index < A.length) {   
            cont = true;
            merged.push(A[index]);
         }
      }
      index++;
   } while (cont);
   return merged;
}

merged = zip([1,3,5,7,9,11], [2,4,6,8]);
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 11]

merged = zip([1, 4, 7], [2, 5, 8], [3, 6, 9])
// [1, 2, 3, 4, 5, 6, 7, 8, 9]

Here is a short way to do it using Array.from() , Array.flat() and Array.filter() : 这是使用Array.from()Array.flat()Array.filter()的简短方法:

 const zip = (a, b) => Array.from( // create an array { length: Math.max(a.length, b.length) }, // as long as the longest of a and b (_, i) => [a[i], b[i]] // fill it with pairs from a and b ).flat().filter(x => x !== undefined); // then flatten the pairs and remove undefined entries console.log(...zip([1, 2, 3, 4, 5, 6, 7, 8], ['a', 'b', 'c', 'd'])); console.log(...zip([1, 2, 3, 4], ['a', 'b', 'c', 'd', 'e', 'f', 'g'])); console.log(...zip([1, 2, 4, 5], [])); console.log(...zip([], ['a', 'b', 'c', 'd'])); 

I thought about this for a while and this is what I came up with. 我想了一会儿,这就是我想出的。 It also supports arbitrary numbers of arrays as input like some of the other answers. 它也支持任意数量的数组作为输入,就像其他一些答案一样。

function merge() {
  var result = [];
  for (var i = 0;;++i) {
    var temp = [];
    for (var j = 0; j < arguments.length; ++j) {
      var atPos = arguments[j].slice(i, i+1);
      if (atPos.length) {
        temp.push(result.push(atPos[0]));
      }
    }
    if (temp.length == 0) {
      return result;
    }
  }
}
var aOne = [1,3,5,7,9,11], aTwo = [2,4,6,8], aResult = [];
while (Math.max(aOne.length, aTwo.length) > 0)
  aResult.push(aOne.shift(), aTwo.shift());
document.writeln('aResult: ' + JSON.stringify(aResult.filter(Boolean)));
// aResult: [1,2,3,4,5,6,7,8,9,11]

The .filter(Boolean) is necessary to remove null values resulting from one of the arrays being empty before the other. 必须使用.filter(Boolean)来删除由于其中一个数组为空而在另一个数组之前为空的null值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM