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]]

当前回答

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

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

其他回答

python zip函数的生成器方法。

function* zip(...arrs){
  for(let i = 0; i < arrs[0].length; i++){
    a = arrs.map(e=>e[i])
    if(a.indexOf(undefined) == -1 ){yield a }else{return undefined;}
  }
}
// use as multiple iterators
for( let [a,b,c] of zip([1, 2, 3, 4], ['a', 'b', 'c', 'd'], ['hi', 'hello', 'howdy', 'how are you']) )
  console.log(a,b,c)

// creating new array with the combined arrays
let outputArr = []
for( let arr of zip([1, 2, 3, 4], ['a', 'b', 'c', 'd'], ['hi', 'hello', 'howdy', 'how are you']) )
  outputArr.push(arr)

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

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)))]

我在纯JS中尝试了一下,想知道上面发布的插件是如何完成这项工作的。这是我的结果。首先我要说的是,我不知道这在IE和类似的软件中会有多稳定。这只是一个快速的模型。

init(); function init() { var one = [0, 1, 2, 3]; var two = [4, 5, 6, 7]; var three = [8, 9, 10, 11, 12]; var four = zip(one, two, one); //returns array //four = zip(one, two, three); //returns false since three.length !== two.length console.log(four); } function zip() { for (var i = 0; i < arguments.length; i++) { if (!arguments[i].length || !arguments.toString()) { return false; } if (i >= 1) { if (arguments[i].length !== arguments[i - 1].length) { return false; } } } var zipped = []; for (var j = 0; j < arguments[0].length; j++) { var toBeZipped = []; for (var k = 0; k < arguments.length; k++) { toBeZipped.push(arguments[k][j]); } zipped.push(toBeZipped); } return zipped; }

虽然不是无懈可击,但还是很有趣。

如果你喜欢ES6:

const zip = (arr,...arrs) =>(
                            arr.map(
                              (v,i) => arrs.reduce((a,arr)=>[...a, arr[i]], [v])))

与其他类似Python的函数一样,pythonic提供了一个zip函数,其额外的好处是返回一个惰性求值迭代器,类似于Python对应的行为:

import {zip, zipLongest} from 'pythonic';

const arr1 = ['a', 'b'];
const arr2 = ['c', 'd', 'e'];
for (const [first, second] of zip(arr1, arr2))
    console.log(`first: ${first}, second: ${second}`);
// first: a, second: c
// first: b, second: d

for (const [first, second] of zipLongest(arr1, arr2))
    console.log(`first: ${first}, second: ${second}`);
// first: a, second: c
// first: b, second: d
// first: undefined, second: e

// unzip
const [arrayFirst, arraySecond] = [...zip(...zip(arr1, arr2))];

我是Pythonic的作者和维护者