Javascript equivalent of Python's zip function

前端 未结 18 1671
天命终不由人
天命终不由人 2020-11-21 07:40

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

For instance, if I have three

相关标签:
18条回答
  • 2020-11-21 07:52

    Like @Brandon, I recommend Underscore's zip function. However, it acts like zip_longest, appending undefined values as needed to return something the length of the longest input.

    I used the mixin method to extend underscore with a zipShortest, which acts like Python's zip, based off of the library's own source for zip.

    You can add the following to your common JS code and then call it as if it were part of underscore: _.zipShortest([1,2,3], ['a']) returns [[1, 'a']], for example.

    // Underscore library addition - zip like python does, dominated by the shortest list
    //  The default injects undefineds to match the length of the longest list.
    _.mixin({
        zipShortest : function() {
            var args = Array.Prototype.slice.call(arguments);
            var length = _.min(_.pluck(args, 'length')); // changed max to min
            var results = new Array(length);
            for (var i = 0; i < length; i++) {
                results[i] = _.pluck(args, "" + i);
            }
            return results;
    }});
    
    0 讨论(0)
  • 2020-11-21 07:52

    I took a run at this in pure JS wondering how the plugins posted above got the job done. Here's my result. I'll preface this by saying that I have no idea how stable this will be in IE and the like. It's just a quick mockup.

    init();
    
    function init() {
        var one = [0, 1, 2, 3];
        var two = [4, 5, 6, 7];
        var three = [8, 9, 10, 11, 12];
        var four = zip(one, two, one);
        //returns array
        //four = zip(one, two, three);
        //returns false since three.length !== two.length
        console.log(four);
    }
    
    function zip() {
        for (var i = 0; i < arguments.length; i++) {
            if (!arguments[i].length || !arguments.toString()) {
                return false;
            }
            if (i >= 1) {
                if (arguments[i].length !== arguments[i - 1].length) {
                    return false;
                }
            }
        }
        var zipped = [];
        for (var j = 0; j < arguments[0].length; j++) {
            var toBeZipped = [];
            for (var k = 0; k < arguments.length; k++) {
                toBeZipped.push(arguments[k][j]);
            }
            zipped.push(toBeZipped);
        }
        return zipped;
    }

    It's not bulletproof, but it's still interesting.

    0 讨论(0)
  • 2020-11-21 07:53

    A variation of the lazy generator solution:

    function* iter(it) {
        yield* it;
    }
    
    function* zip(...its) {
        its = its.map(iter);
        while (true) {
            let rs = its.map(it => it.next());
            if (rs.some(r => r.done))
                return;
            yield rs.map(r => r.value);
        }
    }
    
    for (let r of zip([1,2,3], [4,5,6,7], [8,9,0,11,22]))
        console.log(r.join())
    
    // the only change for "longest" is some -> every
    
    function* zipLongest(...its) {
        its = its.map(iter);
        while (true) {
            let rs = its.map(it => it.next());
            if (rs.every(r => r.done))
                return;
            yield rs.map(r => r.value);
        }
    }
    
    for (let r of zipLongest([1,2,3], [4,5,6,7], [8,9,0,11,22]))
        console.log(r.join())

    And this is the python's classic "n-group" idiom zip(*[iter(a)]*n):

    triples = [...zip(...Array(3).fill(iter(a)))]
    
    0 讨论(0)
  • 2020-11-21 07:55

    1. Npm Module: zip-array

    I found an npm module that can be used as a javascript version of python zip:

    zip-array - A javascript equivalent of Python's zip function. Merges together the values of each of the arrays.

    https://www.npmjs.com/package/zip-array

    2. tf.data.zip() in Tensorflow.js

    Another alternate choice is for Tensorflow.js users: if you need a zip function in python to work with tensorflow datasets in Javascript, you can use tf.data.zip() in Tensorflow.js.

    tf.data.zip() in Tensorflow.js documented at here

    0 讨论(0)
  • 2020-11-21 07:55

    If you are fine with ES6:

    const zip = (arr,...arrs) =>(
                                arr.map(
                                  (v,i) => arrs.reduce((a,arr)=>[...a, arr[i]], [v])))
    
    0 讨论(0)
  • 2020-11-21 07:57

    Modern ES6 example with a generator:

    function *zip (...iterables){
        let iterators = iterables.map(i => i[Symbol.iterator]() )
        while (true) {
            let results = iterators.map(iter => iter.next() )
            if (results.some(res => res.done) ) return
            else yield results.map(res => res.value )
        }
    }
    

    First, we get a list of iterables as iterators. This usually happens transparently, but here we do it explicitly, as we yield step-by-step until one of them is exhausted. We check if any of results (using the .some() method) in the given array is exhausted, and if so, we break the while loop.

    0 讨论(0)
提交回复
热议问题