time-to-botec/squiggle/node_modules/@stdlib/utils/object-inverse/lib/object_inverse.js

123 lines
3.0 KiB
JavaScript
Raw Normal View History

/**
* @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 objectKeys = require( './../../keys' );
var isArray = require( '@stdlib/assert/is-array' );
var isObject = require( '@stdlib/assert/is-plain-object' );
var isObjectLike = require( '@stdlib/assert/is-object-like' );
var isBoolean = require( '@stdlib/assert/is-boolean' ).isPrimitive;
var hasOwnProp = require( '@stdlib/assert/has-own-property' );
// MAIN //
/**
* Inverts an object, such that keys become values and values become keys.
*
* @param {ObjectLike} obj - input object
* @param {Options} [opts] - function options
* @param {boolean} [opts.duplicates=true] - boolean indicating whether to store duplicate keys
* @throws {TypeError} first argument must be object-like
* @throws {TypeError} second argument must an an object
* @throws {TypeError} must provide valid options
* @returns {Object} inverted object
*
* @example
* var out = invert({
* 'a': 'beep',
* 'b': 'boop'
* });
* // returns { 'beep': 'a', 'boop': 'b' }
*
* @example
* var out = invert({
* 'a': 'beep',
* 'b': 'beep'
* });
* // returns { 'beep': [ 'a', 'b' ] }
*
* @example
* var obj = {};
* obj.a = 'beep';
* obj.b = 'boop';
* obj.c = 'beep'; // inserted after `a`
*
* var out = invert( obj, {
* 'duplicates': false
* });
* // returns { 'beep': 'c', 'boop': 'b' }
*/
function invert( obj, opts ) {
var allowDupes = true;
var keys;
var len;
var key;
var val;
var out;
var v;
var i;
if ( !isObjectLike( obj ) ) {
throw new TypeError( 'invalid argument. First argument must be object-like. Value: `' + obj + '`.' );
}
if ( arguments.length > 1 ) {
if ( !isObject( opts ) ) {
throw new TypeError( 'invalid argument. Options arguments must be an object. Value: `' + opts + '`.' );
}
if ( hasOwnProp( opts, 'duplicates' ) ) {
allowDupes = opts.duplicates;
if ( !isBoolean( allowDupes ) ) {
throw new TypeError( 'invalid argument. `duplicates` option must be a boolean primitive. Option: `' + allowDupes + '`.' );
}
}
}
keys = objectKeys( obj );
len = keys.length;
out = {};
if ( allowDupes ) {
for ( i = 0; i < len; i++ ) {
key = keys[ i ];
val = obj[ key ];
if ( !hasOwnProp( out, val ) ) {
out[ val ] = key;
continue;
}
v = out[ val ];
if ( isArray( v ) ) {
out[ val ].push( key );
} else {
out[ val ] = [ v, key ];
}
}
} else {
for ( i = 0; i < len; i++ ) {
key = keys[ i ];
out[ obj[ key ] ] = key;
}
}
return out;
}
// EXPORTS //
module.exports = invert;