Javascript equivalent of Python's zip function

前端 未结 18 1667
天命终不由人
天命终不由人 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:46

    In addition to ninjagecko's excellent and comprehensive answer, all it takes to zip two JS-arrays into a "tuple-mimic" is:

    //Arrays: aIn, aOut
    Array.prototype.map.call( aIn, function(e,i){return [e, aOut[i]];})
    

    Explanation:
    Since Javascript doesn't have a tuples type, functions for tuples, lists and sets wasn't a high priority in the language specification.
    Otherwise, similar behavior is accessible in a straightforward manner via Array map in JS >1.6. (map is actually often implemented by JS engine makers in many >JS 1.4 engines, despite not specified).
    The major difference to Python's zip, izip,... results from map's functional style, since map requires a function-argument. Additionally it is a function of the Array-instance. One may use Array.prototype.map instead, if an extra declaration for the input is an issue.

    Example:

    _tarrin = [0..constructor, function(){}, false, undefined, '', 100, 123.324,
             2343243243242343242354365476453654625345345, 'sdf23423dsfsdf',
             'sdf2324.234dfs','234,234fsf','100,100','100.100']
    _parseInt = function(i){return parseInt(i);}
    _tarrout = _tarrin.map(_parseInt)
    _tarrin.map(function(e,i,a){return [e, _tarrout[i]]})
    

    Result:

    //'('+_tarrin.map(function(e,i,a){return [e, _tarrout[i]]}).join('),\n(')+')'
    >>
    (function Number() { [native code] },NaN),
    (function (){},NaN),
    (false,NaN),
    (,NaN),
    (,NaN),
    (100,100),
    (123.324,123),
    (2.3432432432423434e+42,2),
    (sdf23423dsfsdf,NaN),
    (sdf2324.234dfs,NaN),
    (234,234fsf,234),
    (100,100,100),
    (100.100,100)
    

    Related Performance:

    Using map over for-loops:

    See: What is the most efficient way of merging [1,2] and [7,8] into [[1,7], [2,8]]

    zip tests

    Note: the base types such as false and undefined do not posess a prototypal object-hierarchy and thus do not expose a toString function. Hence these are shown as empty in the output.
    As parseInt's second argument is the base/number radix, to which to convert the number to, and since map passes the index as the second argument to its argument-function, a wrapper function is used.

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

    Along other Python-like functions, pythonic offers a zip function, with the extra benefit of returning a lazy evaluated Iterator, similar to the behaviour of its Python counterpart:

    import {zip, zipLongest} from 'pythonic';
    
    const arr1 = ['a', 'b'];
    const arr2 = ['c', 'd', 'e'];
    for (const [first, second] of zip(arr1, arr2))
        console.log(`first: ${first}, second: ${second}`);
    // first: a, second: c
    // first: b, second: d
    
    for (const [first, second] of zipLongest(arr1, arr2))
        console.log(`first: ${first}, second: ${second}`);
    // first: a, second: c
    // first: b, second: d
    // first: undefined, second: e
    
    // unzip
    const [arrayFirst, arraySecond] = [...zip(...zip(arr1, arr2))];
    

    Disclosure I'm author and maintainer of Pythonic

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

    I modified flm's nifty answer to take an arbitrary number of arrays:

    function* zip(arrays, i = 0) {
      while (arrays[0][i]) {
        yield arrays.map((arr, j) => arr[j < arrays.length - 1 ? i : i++])
      }
     }

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

    The Mochikit library provides this and many other Python-like functions. developer of Mochikit is also a Python fan, so it has the general style of Python, and also the wraps the async calls in a twisted-like framework.

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

    This shaves a line off Ddi's iterator-based answer:

    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);
      }
    }
    
    0 讨论(0)
  • 2020-11-21 07:51

    The Python has two functions: zip and itertools.zip_longest. Implementation on JS/ES6 is like this:

    Implementation Python`s zip on JS/ES6

    const zip = (...arrays) => {
        const length = Math.min(...arrays.map(arr => arr.length));
        return Array.from({ length }, (value, index) => arrays.map((array => array[index])));
    };
    

    Results:

    console.log(zip(
        [1, 2, 3, 'a'],
        [667, false, -378, '337'],
        [111],
        [11, 221]
    ));
    

    [ [ 1, 667, 111, 11 ] ]

    console.log(zip(
        [1, 2, 3, 'a'],
        [667, false, -378, '337'],
        [111, 212, 323, 433, '1111']
    ));
    

    [ [ 1, 667, 111 ], [ 2, false, 212 ], [ 3, -378, 323 ], [ 'a', '337', 433 ] ]

    console.log(zip(
        [1, 2, 3, 'a'],
        [667, false, -378, '337'],
        [111],
        []
    ));
    

    []

    Implementation Python`s zip_longest on JS/ES6

    (https://docs.python.org/3.5/library/itertools.html?highlight=zip_longest#itertools.zip_longest)

    const zipLongest = (placeholder = undefined, ...arrays) => {
        const length = Math.max(...arrays.map(arr => arr.length));
        return Array.from(
            { length }, (value, index) => arrays.map(
                array => array.length - 1 >= index ? array[index] : placeholder
            )
        );
    };
    

    Results:

    console.log(zipLongest(
        undefined,
        [1, 2, 3, 'a'],
        [667, false, -378, '337'],
        [111],
        []
    ));
    

    [ [ 1, 667, 111, undefined ], [ 2, false, undefined, undefined ],
    [ 3, -378, undefined, undefined ], [ 'a', '337', undefined, undefined ] ]

    console.log(zipLongest(
        null,
        [1, 2, 3, 'a'],
        [667, false, -378, '337'],
        [111],
        []
    ));
    

    [ [ 1, 667, 111, null ], [ 2, false, null, null ], [ 3, -378, null, null ], [ 'a', '337', null, null ] ]

    console.log(zipLongest(
        'Is None',
        [1, 2, 3, 'a'],
        [667, false, -378, '337'],
        [111],
        []
    ));
    

    [ [ 1, 667, 111, 'Is None' ], [ 2, false, 'Is None', 'Is None' ],
    [ 3, -378, 'Is None', 'Is None' ], [ 'a', '337', 'Is None', 'Is None' ] ]

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