Javascript 相当于 Python 的 zip 函数
有没有一个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]]
2016年更新:
这是一个更时髦的Ecmascript 6版本:
zip= rows=>rows[0].map((_,c)=>rows.map(row=>row[c]))
Illustration equiv. to Python{}:zip(*args)
> zip([['row0col0', 'row0col1', 'row0col2'],
['row1col0', 'row1col1', 'row1col2']]);
[["row0col0","row1col0"],
["row0col1","row1col1"],
["row0col2","row1col2"]]
(FizzyTea指出ES6具有可变参数语法,因此以下函数定义将像python一样,但请参阅下面的免责声明...这不会是它自己的逆,所以不会等于;虽然正如Matt Kramer指出的那样(就像在普通的python中一样)zip(zip(x))
x
zip(...zip(...x))==x
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可迭代对象)。
下面是一个单行线:
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(...)
上述假设数组的大小相等,因为它们应该是。它还假设您传入单个列表列表参数,这与Python的版本不同,其中参数列表是可变的。如果你想要所有这些“功能”,见下文。它只需要大约2行额外的代码。
以下内容将模仿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()
// []
如果您使用最后两个版本(可变参数又名多参数版本),则 zip 不再是它自己的逆。要模仿Python中的习语,当您想要反转zip函数或想要以类似方式将可变数量的列表作为输入时,您需要这样做。zip(*[...])
zip.apply(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 数组推导或生成器。range(...)
查看库下划线。
Underscore 提供了 100 多个函数,既支持您最喜欢的 workaday 函数助手:map、filter、invoke,也支持更专业的好东西:函数绑定、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]]