182 lines
4.6 KiB
JavaScript
182 lines
4.6 KiB
JavaScript
|
/**
|
||
|
* @license Apache-2.0
|
||
|
*
|
||
|
* Copyright (c) 2018 The Stdlib Authors.
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*/
|
||
|
|
||
|
'use strict';
|
||
|
|
||
|
// MODULES //
|
||
|
|
||
|
var isBoolean = require( '@stdlib/assert/is-boolean' ).isPrimitive;
|
||
|
var isObject = require( '@stdlib/assert/is-plain-object' );
|
||
|
var isArray = require( '@stdlib/assert/is-array' );
|
||
|
var hasOwnProp = require( '@stdlib/assert/has-own-property' );
|
||
|
|
||
|
|
||
|
// MAIN //
|
||
|
|
||
|
/**
|
||
|
* Generates array tuples from input arrays.
|
||
|
*
|
||
|
* @param {...Array} arr - input arrays to be zipped
|
||
|
* @param {Object} [opts] - function options
|
||
|
* @param {boolean} [opts.trunc=true] - boolean indicating whether to truncate arrays longer than the shortest input array
|
||
|
* @param {*} [opts.fill=null] - fill value used for arrays of unequal length
|
||
|
* @param {boolean} [opts.arrays=false] - boolean indicating whether an input array should be interpreted as an array of arrays to be zipped
|
||
|
* @throws {TypeError} must provide array arguments
|
||
|
* @throws {Error} must provide at least one array
|
||
|
* @throws {TypeError} options argument must be an object
|
||
|
* @throws {TypeError} must provide valid options
|
||
|
* @returns {Array} output array of arrays
|
||
|
*
|
||
|
* @example
|
||
|
* var zipped = zip( [ 1, 2 ], [ 'a', 'b' ] );
|
||
|
* // returns [ [ 1, 'a' ], [ 2, 'b' ] ]
|
||
|
*
|
||
|
* @example
|
||
|
* var zipped = zip( [ 1, 2, 3 ], [ 'a', 'b' ] );
|
||
|
* // returns [ [ 1, 'a' ], [ 2, 'b' ] ]
|
||
|
*
|
||
|
* @example
|
||
|
* var opts = {
|
||
|
* 'trunc': false
|
||
|
* };
|
||
|
*
|
||
|
* var zipped = zip( [ 1, 2, 3 ], [ 'a', 'b' ], opts );
|
||
|
* // returns [ [ 1, 'a' ], [ 2, 'b' ], [ 3, null ] ]
|
||
|
*
|
||
|
* @example
|
||
|
* var opts = {
|
||
|
* 'trunc': false,
|
||
|
* 'fill': ''
|
||
|
* };
|
||
|
*
|
||
|
* var zipped = zip( [ 1, 2, 3 ], [ 'a', 'b' ], opts );
|
||
|
* // returns [ [ 1, 'a' ], [ 2, 'b' ], [ 3, '' ] ]
|
||
|
*
|
||
|
* @example
|
||
|
* var arr = [ [ 1, 2 ], [ 'a', 'b' ] ];
|
||
|
*
|
||
|
* // Default behavior:
|
||
|
* var zipped = zip( arr );
|
||
|
* // returns [ [ [ 1, 2 ] ], [ [ 'a', 'b' ] ] ]
|
||
|
*
|
||
|
* // Array of arrays:
|
||
|
* zipped = zip( arr, { 'arrays': true } );
|
||
|
* // returns [ [ 1, 'a' ], [ 2, 'b' ] ]
|
||
|
*/
|
||
|
function zip() {
|
||
|
var nargs;
|
||
|
var args;
|
||
|
var fill;
|
||
|
var opts;
|
||
|
var arg;
|
||
|
var flg;
|
||
|
var len;
|
||
|
var arr;
|
||
|
var out;
|
||
|
var val;
|
||
|
var i;
|
||
|
var j;
|
||
|
|
||
|
opts = {};
|
||
|
fill = null;
|
||
|
args = Array.prototype.slice.call( arguments );
|
||
|
nargs = args.length;
|
||
|
|
||
|
for ( i = 0; i < nargs-1; i++ ) {
|
||
|
if ( !isArray( args[i] ) ) {
|
||
|
throw new TypeError( 'invalid argument. Must provide array arguments. Value: `' + args[i] + '`.' );
|
||
|
}
|
||
|
}
|
||
|
arg = args[ nargs-1 ];
|
||
|
flg = isObject( arg );
|
||
|
if ( !flg && !isArray( arg ) ) {
|
||
|
throw new TypeError( 'invalid argument. Last argument must be either an array or an options object. Value: `' + arg + '`.' );
|
||
|
}
|
||
|
if ( flg ) {
|
||
|
opts = args.pop();
|
||
|
}
|
||
|
nargs = args.length;
|
||
|
if ( nargs === 0 ) {
|
||
|
throw new Error( 'insufficient input arguments. Must provide at least one array.' );
|
||
|
}
|
||
|
if ( hasOwnProp( opts, 'trunc' ) ) {
|
||
|
if ( !isBoolean( opts.trunc ) ) {
|
||
|
throw new TypeError( 'invalid option. `trunc` option must be a boolean. Value: `' + opts.trunc + '`.' );
|
||
|
}
|
||
|
} else {
|
||
|
opts.trunc = true;
|
||
|
}
|
||
|
if ( hasOwnProp( opts, 'fill' ) ) {
|
||
|
fill = opts.fill;
|
||
|
}
|
||
|
if ( hasOwnProp( opts, 'arrays' ) ) {
|
||
|
if ( !isBoolean( opts.arrays ) ) {
|
||
|
throw new TypeError( 'invalid option. `arrays` option must be a boolean. Value: `' + opts.arrays + '`.' );
|
||
|
}
|
||
|
} else {
|
||
|
opts.arrays = false;
|
||
|
}
|
||
|
if ( nargs === 1 && opts.arrays ) {
|
||
|
// Treat the lone array argument as an array of arrays to be zipped...
|
||
|
args = args[ 0 ];
|
||
|
nargs = args.length;
|
||
|
}
|
||
|
len = args[ 0 ].length;
|
||
|
if ( opts.trunc ) {
|
||
|
// Find the min array length...
|
||
|
for ( i = 0; i < nargs; i++ ) {
|
||
|
val = args[ i ].length;
|
||
|
if ( val < len ) {
|
||
|
len = val;
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
// Find the max array length...
|
||
|
for ( i = 0; i < nargs; i++ ) {
|
||
|
val = args[ i ].length;
|
||
|
if ( val > len ) {
|
||
|
len = val;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
out = new Array( len );
|
||
|
for ( j = 0; j < len; j++ ) {
|
||
|
// Temporary array to store tuples...
|
||
|
arr = new Array( nargs );
|
||
|
|
||
|
// Create the tuples...
|
||
|
for ( i = 0; i < nargs; i++ ) {
|
||
|
arg = args[ i ];
|
||
|
|
||
|
// If an array is too short, use a fill value...
|
||
|
if ( arg.length <= j ) {
|
||
|
arr[ i ] = fill;
|
||
|
continue;
|
||
|
}
|
||
|
arr[ i ] = arg[ j ];
|
||
|
}
|
||
|
out[ j ] = arr;
|
||
|
}
|
||
|
return out;
|
||
|
}
|
||
|
|
||
|
|
||
|
// EXPORTS //
|
||
|
|
||
|
module.exports = zip;
|