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的函数一样,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的作者和维护者

其他回答

除了ninjagecko出色而全面的回答外,将两个js数组压缩成“元组模拟”所需要的是:

//Arrays: aIn, aOut
Array.prototype.map.call( aIn, function(e,i){return [e, aOut[i]];})

Explanation: Since Javascript doesn't have a tuples type, functions for tuples, lists and sets wasn't a high priority in the language specification. Otherwise, similar behavior is accessible in a straightforward manner via Array map in JS >1.6. (map is actually often implemented by JS engine makers in many >JS 1.4 engines, despite not specified). The major difference to Python's zip, izip,... results from map's functional style, since map requires a function-argument. Additionally it is a function of the Array-instance. One may use Array.prototype.map instead, if an extra declaration for the input is an issue.

例子:

_tarrin = [0..constructor, function(){}, false, undefined, '', 100, 123.324,
         2343243243242343242354365476453654625345345, 'sdf23423dsfsdf',
         'sdf2324.234dfs','234,234fsf','100,100','100.100']
_parseInt = function(i){return parseInt(i);}
_tarrout = _tarrin.map(_parseInt)
_tarrin.map(function(e,i,a){return [e, _tarrout[i]]})

结果:

//'('+_tarrin.map(function(e,i,a){return [e, _tarrout[i]]}).join('),\n(')+')'
>>
(function Number() { [native code] },NaN),
(function (){},NaN),
(false,NaN),
(,NaN),
(,NaN),
(100,100),
(123.324,123),
(2.3432432432423434e+42,2),
(sdf23423dsfsdf,NaN),
(sdf2324.234dfs,NaN),
(234,234fsf,234),
(100,100,100),
(100.100,100)

相关的性能:

使用map over for loops:

请参阅:将[1,2]和[7,8]合并为[[1,7],[2,8]的最有效方法是什么

注意:基本类型如false和undefined不具有原型对象层次结构,因此不公开toString函数。因此,这些在输出中显示为空。 由于parseInt的第二个参数是基数/数字基数,要将数字转换为基数/数字基数,并且由于map将索引作为第二个参数传递给它的参数函数,因此使用包装器函数。

你可以使用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 ]]

原始答案(见下文更新)

我修改了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)))

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

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

查看下划线库。

Underscore提供了超过100个函数,这些函数既支持你最喜欢的日常函数帮助:映射、过滤器、调用——也支持更专业的功能:函数绑定、javascript模板、创建快速索引、深度等式测试等等。

-说说制作它的人

我最近开始专门为zip()函数使用它,它给我留下了很好的第一印象。我使用jQuery和CoffeeScript,它只是完美地与他们。下划线就在他们离开的地方,到目前为止,它还没有让我失望。哦,顺便说一下,它只缩小了3kb。

看看吧:

_.zip(['moe', 'larry', 'curly'], [30, 40, 50], [true, false, false]);
// returns [["moe", 30, true], ["larry", 40, false], ["curly", 50, false]]