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

当前回答

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)

其他回答

原始答案(见下文更新)

我修改了flm的漂亮答案,以获取任意数量的数组:

函数* zip(数组,I = 0) { 虽然(我< Math.min(…arrays.map(({长度})= >长度))){ 收益率数组。Map ((arr, j) => arr[j <数组。长度- 1 ?I: i++]) } }

更新后的答案

正如Tom Pohl所指出的,这个函数不能处理数组中有假值的数组。下面是一个更新/改进的版本,可以处理任何类型和长度不等的数组:

函数* zip(数组,I = 0) { 虽然(我< Math.min(…arrays.map (arr = > arr.length))) { 收益率数组。Map ((arr, j) => arr[j <数组。长度- 1 ?I: i++]) } } Const arr1 = [false,0,1,2] Const arr2 = [100,null,99,98,97] Const arr3 = [7,8,undefined,"monkey","banana"] console.log(…zip ([arr1、arr2 arr3)))

如果你喜欢ES6:

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

Python有两个压缩序列的函数:zip和itertools.zip_longest。Javascript中相同功能的实现如下所示:

Python的zip在JS/ES6上的实现

const zip = (...arrays) => {
    const length = Math.min(...arrays.map(arr => arr.length));
    return Array.from({ length }, (value, index) => arrays.map((array => array[index])));
};

结果:

console.log(zip(
    [1, 2, 3, 'a'],
    [667, false, -378, '337'],
    [111],
    [11, 221]
));

[[1, 667, 111, 11]

console.log(zip(
    [1, 2, 3, 'a'],
    [667, false, -378, '337'],
    [111, 212, 323, 433, '1111']
));

[[1、667、111],[2,假的,212年],[3、-378、323],[' a ', “337”,433]]

console.log(zip(
    [1, 2, 3, 'a'],
    [667, false, -378, '337'],
    [111],
    []
));

[]

Python的zip_longest在JS/ES6上的实现

(https://docs.python.org/3.5/library/itertools.html?highlight=zip_longest # itertools.zip_longest)

const zipLongest = (placeholder = undefined, ...arrays) => {
    const length = Math.max(...arrays.map(arr => arr.length));
    return Array.from(
        { length }, (value, index) => arrays.map(
            array => array.length - 1 >= index ? array[index] : placeholder
        )
    );
};

结果:

console.log(zipLongest(
    undefined,
    [1, 2, 3, 'a'],
    [667, false, -378, '337'],
    [111],
    []
));

[[1,667, 111, undefined], [2, false, undefined, undefined], [3, -378, undefined, undefined], ['a', '337', undefined, 未定义

console.log(zipLongest(
    null,
    [1, 2, 3, 'a'],
    [667, false, -378, '337'],
    [111],
    []
));

[[1, 667, 111, null], [2, false, null, null], [3, -378, Null, Null], ['a', '337', Null, Null]]

console.log(zipLongest(
    'Is None',
    [1, 2, 3, 'a'],
    [667, false, -378, '337'],
    [111],
    []
));

[[1,667, 111, 'Is None'], [2, false, 'Is None', 'Is None'], [3, -378,“没有”,“没有 ' ], [ ' ”、“337”、“没有”、“ 没有']]

这将从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);
  }
}

你可以使用ES6来创建实用函数。

控制台。json = obj => console.log(json .stringify(obj)); Const zip = (arr,…arrs) => 加勒比海盗。Map ((val, i) => arrs。Reduce ((a, arr) =>[…]A, arr[i]], [val])); / /实例 Const array1 = [1,2,3]; Const array2 = ['a','b','c']; Const array3 = [4,5,6]; 控制台。json (zip (array1 array2));/ /[[1, "一个"],[2,“b”],[3,“c”]] 控制台。Json (zip(array1, array2, array3));/ /[[1”“4],[2“b”5],[3“c”6]]

但是,在上述解决方案中,第一个数组的长度定义了输出数组的长度。

这里有一个解决方案,你可以更好地控制它。这有点复杂,但值得。

function _zip(func, args) { const iterators = args.map(arr => arr[Symbol.iterator]()); let iterateInstances = iterators.map((i) => i.next()); ret = [] while(iterateInstances[func](it => !it.done)) { ret.push(iterateInstances.map(it => it.value)); iterateInstances = iterators.map((i) => i.next()); } return ret; } const array1 = [1, 2, 3]; const array2 = ['a','b','c']; const array3 = [4, 5, 6]; const zipShort = (...args) => _zip('every', args); const zipLong = (...args) => _zip('some', args); console.log(zipShort(array1, array2, array3)) // [[1, 'a', 4], [2, 'b', 5], [3, 'c', 6]] console.log(zipLong([1,2,3], [4,5,6, 7])) // [ // [ 1, 4 ], // [ 2, 5 ], // [ 3, 6 ], // [ undefined, 7 ]]