Last active
August 29, 2015 14:02
-
-
Save barneycarroll/e67d36f4fc9430ab2ef6 to your computer and use it in GitHub Desktop.
_.superMerge: Like merge, but concatenates plucked arrays (rather than overwriting with the rightmost).
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
_.mixin( { | |
// Like uniq, but tests for equivalence rather than identity. | |
// Does this by running comparison on stringified representations. | |
// DOM nodes and other objects with circular references can't be stringified and will break. | |
looseUniq : function uniqBasedOnStringify( source ){ | |
var output = _( source ) | |
.map( function stringify( x ){ return JSON.stringify( x ); } ) | |
.uniq() | |
.map( function parse( x ){ return JSON.parse( x ); } ) | |
.valueOf(); | |
return output; | |
}, | |
// Like pluck, but takes an array of keys. eg: | |
// _.deepPluck( DOMelements, [ 'parentNode', 'parentNode', 'id' ] ); | |
// Useful recurssion wrapper when array is generated programmatically. | |
deepPluck : function deepPluck( sources, sourceKeys ){ | |
var keys = _.clone( sourceKeys ); | |
return ( function recursivePluck( sources, keys ){ | |
var key = keys.shift(); | |
var candidates = _.filter( sources, function hasKey( source ){ return _.has( source, key ); } ); | |
var pluck = _.pluck( candidates, key ); | |
if( keys.length ){ | |
return recursivePluck( pluck, keys ); | |
} | |
return pluck; | |
}( sources, keys ) ); | |
}, | |
// Like merge, but concatenates plucked arrays (rather than overwriting with the rightmost). eg: | |
// _.superMerge( { a: 1, b: [ 1 , 2 ] }, { c: 3, b: [ 3, 4 ] } ); // => { a: 1, c: 3, b: [ 1, 2, 3, 4 ] }; | |
superMerge : function mergeAndConcatArrays(){ | |
var sources = _.toArray( arguments ); | |
var merge = _.merge.apply( _, [ {} ].concat( sources ) ); | |
void function findArrays( object, path ){ | |
_.each( object, function ( value, key ){ | |
var currentPath = _( path ).clone(); | |
currentPath.push( key ); | |
if( _.isArray( value ) ){ | |
object[ key ] = _( sources ) | |
.deepPluck( currentPath ) | |
.looseUniq() | |
.flatten( true ) | |
.valueOf(); | |
} | |
else if( _.isObject( value ) ){ | |
findArrays( value, currentPath ); | |
} | |
} ); | |
}( merge, [] ); | |
return ( sources[ 0 ] = merge ); | |
} | |
} ); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment