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]]
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
其他回答
如果你喜欢ES6:
const zip = (arr,...arrs) =>(
arr.map(
(v,i) => arrs.reduce((a,arr)=>[...a, arr[i]], [v])))
没有等价的函数。如果你只有几个数组,你应该使用for循环获取一个索引,然后使用索引访问数组:
var array1 = [1, 2, 3];
var array2 = ['a','b','c'];
for (let i = 0; i < Math.min(array1.length, array2.length); i++) {
doStuff(array1[i], array2[i]);
}
如果你有更多的数组,你可以在数组上有一个内循环。
1. 模块:zip-array
我发现了一个npm模块,可以用作python zip的javascript版本:
zip-array——javascript中类似于Python的zip函数。将每个数组的值合并在一起。
https://www.npmjs.com/package/zip-array
2. Tensorflow.js中的tf.data.zip()
tensorflow .js用户的另一个替代选择是:如果你需要python中的zip函数来处理Javascript中的tensorflow数据集,你可以使用tensorflow .js中的tf.data.zip()。
Tensorflow.js中的tf.data.zip()文档在这里
这将从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);
}
}
2016年更新:
下面是一个更时髦的Ecmascript 6版本:
zip= rows=>rows[0].map((_,c)=>rows.map(row=>row[c]))
对应于Python{zip(*args)}的插图:
> zip([['row0col0', 'row0col1', 'row0col2'],
['row1col0', 'row1col1', 'row1col2']]);
[["row0col0","row1col0"],
["row0col1","row1col1"],
["row0col2","row1col2"]]
(FizzyTea指出ES6有可变参数语法,所以下面的函数定义将像python一样,但请参见下面的免责声明…它不是它自己的逆函数所以zip(zip(x))不等于x;尽管正如Matt Kramer指出的那样,zip(…zip(…x))==x(就像常规python中的zip(*zip(*x))==x)))
Python{zip}的替代定义:
> zip = (...rows) => [...rows[0]].map((_,c) => rows.map(row => row[c]))
> zip( ['row0col0', 'row0col1', 'row0col2'] ,
['row1col0', 'row1col1', 'row1col2'] );
// note zip(row0,row1), not zip(matrix)
same answer as above
(请注意…语法现在可能存在性能问题,将来也可能存在,因此如果使用带有可变参数的第二个答案,可能需要对其进行性能测试。也就是说,自从它被纳入标准已经有一段时间了。)
如果你想在字符串上使用它,一定要注意它的附录(也许现在用es6 iterables有更好的方法)。
这里有一句话:
function zip(arrays) {
return arrays[0].map(function(_,i){
return arrays.map(function(array){return array[i]})
});
}
// > zip([[1,2],[11,22],[111,222]])
// [[1,11,111],[2,22,222]]]
// If you believe the following is a valid return value:
// > zip([])
// []
// then you can special-case it, or just do
// return arrays.length==0 ? [] : arrays[0].map(...)
上面假设数组的大小相等,因为它们应该是相等的。它还假设你传递了一个单独的list of lists参数,不像Python版本的参数列表是可变的。如果你想要所有这些“特性”,请参见下面。它只需要额外的两行代码。
下面将模拟Python在数组大小不相等的边缘情况下的zip行为,默默地假装数组中较长的部分不存在:
function zip() {
var args = [].slice.call(arguments);
var shortest = args.length==0 ? [] : args.reduce(function(a,b){
return a.length<b.length ? a : b
});
return shortest.map(function(_,i){
return args.map(function(array){return array[i]})
});
}
// > zip([1,2],[11,22],[111,222,333])
// [[1,11,111],[2,22,222]]]
// > zip()
// []
这将模拟Python的itertools.zip_longest行为,在未定义数组的地方插入undefined:
function zip() {
var args = [].slice.call(arguments);
var longest = args.reduce(function(a,b){
return a.length>b.length ? a : b
}, []);
return longest.map(function(_,i){
return args.map(function(array){return array[i]})
});
}
// > zip([1,2],[11,22],[111,222,333])
// [[1,11,111],[2,22,222],[null,null,333]]
// > zip()
// []
如果你使用这最后两个版本(可变变量aka。多参数版本),那么zip就不再是它自己的逆。要模仿Python中的zip(*[…])习语,需要执行zip。当您想要反转zip函数,或者如果您想类似地使用可变数量的列表作为输入时,应用(this,[…])。
附录:
要使此句柄为任何可迭代对象(例如,在Python中,您可以对字符串、范围、映射对象等使用zip),您可以定义以下内容:
function iterView(iterable) {
// returns an array equivalent to the iterable
}
然而,如果你以下面的方式写zip,即使这样也不需要:
function zip(arrays) {
return Array.apply(null,Array(arrays[0].length)).map(function(_,i){
return arrays.map(function(array){return array[i]})
});
}
演示:
> JSON.stringify( zip(['abcde',[1,2,3,4,5]]) )
[["a",1],["b",2],["c",3],["d",4],["e",5]]
(或者你可以使用一个范围(…)python风格的函数(如果你已经写过的话)。最终,您将能够使用ECMAScript数组推导式或生成器。)