Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

Is there a javascript equivalent of Python's zip function?

(是否有与Python的zip函数等效的JavaScript?)

That is, given multiple 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]]
  ask by pq. translate from so

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
237 views
Welcome To Ask or Share your Answers For Others

1 Answer

2016 update:

(2016年更新:)

Here's a snazzier Ecmascript 6 version:

(这是一个时髦的Ecmascript 6版本:)

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

Illustration equiv.

(相当于插图。)

to Python { zip(*args) }:

(到Python { zip(*args) }:)

> 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 function definition will act like python, but see below for disclaimer... this will not be its own inverse so zip(zip(x)) will not equal x ; though as Matt Kramer points out zip(...zip(...x))==x (like in regular python zip(*zip(*x))==x ))

((并且FizzyTea指出ES6具有可变参数语法,因此以下函数定义将类似于python,但请参见下文的免责声明...这将不是其自身的反函数,因此zip(zip(x))将不等于x ;尽管正如Matt Kramer指出的那样zip(...zip(...x))==x (就像在常规python zip(*zip(*x))==x )))

Alternative definition equiv.

(等效定义)

to Python { zip }:

(到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

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

(它还假定您传入一个lists参数列表,这与Python版本的参数列表是可变参数不同。)

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:

(下面将模拟在数组大小不相等的极端情况下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()
// []

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

(这将模仿Python的itertools.zip_longest行为,在undefined数组的地方插入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()
// []

If you use these last two version (variadic aka. multiple-argument versions), then zip is no longer its own inverse.

(如果您使用最后两个版本(可变参数,也称为多参数版本),则zip不再是其自身的反函数。)

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.

(要模仿Python中的zip(*[...])习惯用法,当您想反转zip函数或想要类似地使用变量时zip.apply(this, [...])需要执行zip.apply(this, [...])输入的列表数。)


addendum :

(附录 :)

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

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

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:

(但是,如果您通过以下方式编写zip ,则即使没有必要:)

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

((或者,如果您已经编写过,则可以使用range(...) Python风格的函数。最终,您将能够使用ECMAScript数组推导或生成器。))


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...