javascript中是否有类似于Python的zip函数?也就是说,给定多个相等长度的数组,创建一个由对组成的数组。

例如,如果我有三个这样的数组:

var array1 = [1, 2, 3];
var array2 = ['a','b','c'];
var array3 = [4, 5, 6];

输出数组应该是:

var outputArray = [[1,'a',4], [2,'b',5], [3,'c',6]]

当前回答

带有生成器的现代ES6示例:

function *zip (...iterables){
    let iterators = iterables.map(i => i[Symbol.iterator]() )
    while (true) {
        let results = iterators.map(iter => iter.next() )
        if (results.some(res => res.done) ) return
        else yield results.map(res => res.value )
    }
}

首先,我们得到一个iterables列表作为迭代器。这通常是透明地发生的,但在这里我们明确地进行,因为我们逐步让步,直到其中一个耗尽。我们检查给定数组中的任何结果(使用.some()方法)是否已耗尽,如果是,则中断while循环。

其他回答

您可以减少数组的数组,并通过获取内部数组的索引的结果来映射新数组。

Var array1 = [1,2,3], Array2 = ['a','b','c'], Array3 = [4,5,6], 数组= [array1, array2, array3], 转置=数组。减少((r) = > a.map ((v, i) = > (r(我)| | []).concat (v)), []); console.log(转置);

有趣的传播。

常量 转置= (r, a) => a.map((v, i) =>[…](r[i] || []), v]), Array1 = [1,2,3], Array2 = ['a','b','c'], Array3 = [4,5,6], 转置= [array1, array2, array3]。减少(转置,[]); console.log(转置);

这将从Ddi基于迭代器的答案中删除一行:

function* zip(...toZip) {
  const iterators = toZip.map((arg) => arg[Symbol.iterator]());
  const next = () => toZip = iterators.map((iter) => iter.next());
  while (next().every((item) => !item.done)) {
    yield toZip.map((item) => item.value);
  }
}

我不是一个javascript的人,但我觉得这些答案是试图找到最可爱和最聪明的解决方案使用数组。这是很好的,但对于像我这样不每天使用javascript的人来说,这里有一些可能更可读的替代方案。

也许有一种方法可以避免一些可爱而聪明的代码:

function zip(a,b){
    // pre-allocate an array to hold the results 
    rval=Array(Math.max(a.length, b.length));
    for(i=0; i<rval.length; i++){ 
        rval[i]=[a[i],b[i]] 
    }
    return rval
}

如果你喜欢生成器:

function* _zip(a,b){
    len = Math.max(a.length, b.length) // handle different sized arrays
    for(i=0; i<len; i++) { yield [a[i],b[i]] }
}

或者如果你真的想使用Array.map:

function map(a,b){
    x = a.length > b.length ? a : b // call map on the biggest array
    return x.map((_,i)=>[a[i],b[i]])
}

就像我说的,我不是一个日常使用javascript的人,所以这些不是最优雅的解决方案,但它们对我来说是可读的。

我创建了一个简单的函数,通过一个选项来提供一个拉链函数

function zip(zipper, ...arrays) {
    if (zipper instanceof Array) {
        arrays.unshift(zipper)
        zipper = (...elements) => elements
    }

    const length = Math.min(...arrays.map(array => array.length))
    const zipped = []

    for (let i = 0; i < length; i++) {
        zipped.push(zipper(...arrays.map(array => array[i])))
    }

    return zipped
}

https://gist.github.com/AmrIKhudair/4b740149c29c492859e00f451832975b

惰性生成器解决方案的一个变体:

function* iter(it) { yield* it; } function* zip(...its) { its = its.map(iter); while (true) { let rs = its.map(it => it.next()); if (rs.some(r => r.done)) return; yield rs.map(r => r.value); } } for (let r of zip([1,2,3], [4,5,6,7], [8,9,0,11,22])) console.log(r.join()) // the only change for "longest" is some -> every function* zipLongest(...its) { its = its.map(iter); while (true) { let rs = its.map(it => it.next()); if (rs.every(r => r.done)) return; yield rs.map(r => r.value); } } for (let r of zipLongest([1,2,3], [4,5,6,7], [8,9,0,11,22])) console.log(r.join())

这是python经典的“n-group”习语zip(*[iter(a)]*n):

triples = [...zip(...Array(3).fill(iter(a)))]