Javascript的等效Python的zip函数 [英] Javascript equivalent of Python's zip function

查看:243
本文介绍了Javascript的等效Python的zip函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否有与Python的zip函数相当的javascript?也就是说,给定两个长度相等的数组创建一个数组对。



例如,如果我有三个看起来像这样的数组:

  var array1 = [1,2,3]; 
var array2 = ['a','b','c'];
var array3 = [4,5,6];

输出数组应该是:

  var output array:[[1,'a',4],[2,'b',5],[3,'c',6]] 


解决方案

2016更新: b

下面是一个时髦的Ecmascript 6版本:

  zip = rows => rows [0]。 map((_,c)=> rows.map(row => row [c]))

插图:

 > zip [['row0col0','row0col1','row0col2'],
['row1col0','row1col1','row1col2']]);
[[row0col0,row1col0],
[row0col1,row1col1],
[row0col2,row1col2]]
zip(zip(x))
不会等于 x :)

 > zip =(... rows)=> map((_,c)=> rows.map(row => row [c]))
> zip(['row0col0','row0col1','row0col2'],
['row1col0','row1col1','row1col2']);
//注释zip(row0,row1),不是zip(矩阵)
与上面相同的答案

(请注意, ... 语法在这个时候可能会有性能问题,并且可能在将来会有问题,所以如果您使用第二个答案可能需要进行全面测试。)






以下是一个oneliner:

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

//如果您确信以下内容是有效的返回值:
//> zip([])
// []
//那么你可以特殊情况下,或者只是做
//返回arrays.length == 0? []:arrays [0] .map(...)






以上假定数组的大小相同,因为它们应该是。它还假设你传入一个列表参数列表,与参数列表是可变参数的Python版本不同。 如果您想要所有这些功能,请参阅下文。它只需要大约2行代码。



以下内容将模仿Python的 zip 行为,数组的大小不一样,默默地假装数组的较长部分不存在:
$ b

函数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()
// []

如果您使用这两个版本(variadic aka 。多参数版本),然后zip不再是它自己的逆。为了模拟Python中的 zip(* [...])成语,您需要执行 zip.apply(this,[... ])当你想颠倒压缩函数,或者你想同样有一个可变数量的列表作为输入。






附录

为了使这个句柄成为可迭代的(例如在Python中,可以使用 在字符串,范围,地图对象等上),您可以定义以下内容:

 函数iterView(iterable){
//返回一个等价于可迭代
的数组

然而,如果您在以下 zip > way ,即使这样也不是必须的:
$ b

  function zip(数组){
返回Array.apply(null,Array(arrays [0] .length))。map(function(_,i){
return arrays.map(function(arra y){return array [i]})
});
}

演示:

 > JSON.stringify(zip(['abcde',[1,2,3,4,5]]))
[[a,1],[b,2],[c ,3,[d,4],[e,5]]

或者你可以使用范围(...) Python风格的函数,如果你已经编写了一个函数,最终你将能够使用ECMAScript数组理解或者生成器。)

Is there a javascript equivalent of Python's zip function? That is, given two arrays of equal lengths create an array of pairs.

For instance, if I have three arrays that look like this:

var array1 = [1, 2, 3];
var array2 = ['a','b','c'];
var array3 = [4, 5, 6];

The output array should be:

var output array:[[1,'a',4], [2,'b',5], [3,'c',6]]

解决方案

2016 update:

Here's a snazzier Ecmascript 6 version:

zip= rows=>rows[0].map((_,c)=>rows.map(row=>row[c]))

Illustration:

> zip([['row0col0', 'row0col1', 'row0col2'],
       ['row1col0', 'row1col1', 'row1col2']]);
[["row0col0","row1col0"],
 ["row0col1","row1col1"],
 ["row0col2","row1col2"]]

(and FizzyTea points out that ES6 has variadic argument syntax, so the following will act like python, but see below for disclaimer... this will not be its own inverse so zip(zip(x)) will not equal x:)

> 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

(Do note that the ... syntax may have performance issues at this time, and possibly in the future, so if you use the second answer with variadic arguments, you may want to perf test it.)


Here's a oneliner:

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(...)


The above assumes that the arrays are of equal size, as they should be. It also assumes you pass in a single list of lists argument, unlike Python's version where the argument list is variadic. If you want all of these "features", see below. It takes just about 2 extra lines of code.

The following will mimic Python's zip behavior on edge cases where the arrays are not of equal size, silently pretending the longer parts of arrays don't exist:

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()
// []

This will mimic Python's itertools.zip_longest behavior, inserting undefined where arrays are not defined:

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()
// []

If you use these last two version (variadic aka. multiple-argument versions), then zip is no longer its own inverse. To mimic the zip(*[...]) idiom from Python, you will need to do zip.apply(this, [...]) when you want to invert the zip function or if you want to similarly have a variable number of lists as input.


addendum:

To make this handle any iterable (e.g. in Python you can use zip on strings, ranges, map objects, etc.), you could define the following:

function iterView(iterable) {
    // returns an array equivalent to the iterable
}

However if you write zip in the following way, even that won't be necessary:

function zip(arrays) {
    return Array.apply(null,Array(arrays[0].length)).map(function(_,i){
        return arrays.map(function(array){return array[i]})
    });
}

Demo:

> JSON.stringify( zip(['abcde',[1,2,3,4,5]]) )
[["a",1],["b",2],["c",3],["d",4],["e",5]]

(Or you could use a range(...) Python-style function if you've written one already. Eventually you will be able to use ECMAScript array comprehensions or generators.)

这篇关于Javascript的等效Python的zip函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆