Last active
January 6, 2016 18:58
-
-
Save PAEz/57a99677e65f7d39a7a9 to your computer and use it in GitHub Desktop.
Object iterate, toPath, map
This file contains hidden or 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
function objectIterate(obj, callback, stack, cache) { | |
cache = cache || []; | |
for (var property in obj) { | |
if (obj.hasOwnProperty(property)) { | |
var value = obj[property]; | |
if (typeof value == "object" && value !== null) { | |
if (cache.indexOf(value) !== -1) { | |
// Circular reference found, discard key | |
return; | |
} | |
cache.push(value); | |
objectIterate(value, callback, (stack ? stack + '.' : '') + property, cache); | |
} else { | |
callback((stack ? stack + '.' : '') + property, obj, property); | |
} | |
} | |
} | |
} | |
// Nearly there now | |
function objectIterate(obj, callback, arrays, objects, stack, cache, inArray) { | |
if (cache === undefined) { | |
cache = []; | |
} | |
if (stack === undefined) { | |
stack = ''; | |
} | |
for (var property in obj) { | |
if (obj.hasOwnProperty(property)) { | |
var value = obj[property]; | |
if (typeof value == "object" && value !== null) { | |
if (cache.indexOf(value) !== -1) { | |
// Circular reference found, discard key | |
continue; | |
} | |
cache.push(value); | |
var isArray = Array.isArray(value); | |
if (objects) { | |
var nextStack = ''; | |
if (inArray) | |
nextStack = '[' + property + ']'; | |
else if (!stack.length) | |
nextStack = property; | |
else | |
nextStack += '.' + property; | |
callback(stack + nextStack, obj, property); | |
} | |
if (!(!arrays && isArray)) { | |
var newStack = ''; | |
if (!stack.length) | |
newStack = property; | |
else | |
newStack = (inArray ? '[' + property + ']' : '.' + property); | |
objectIterate(value, callback, arrays, objects, stack + newStack, cache, isArray); | |
} | |
} else { | |
// property | |
var nextStack = ''; | |
if (inArray) | |
nextStack = '[' + property + ']'; | |
else if (!stack.length) | |
nextStack = property; | |
else | |
nextStack += '.' + property; | |
callback(stack + nextStack, obj, property); | |
} | |
} | |
} | |
} | |
function objectToPath(obj, prop, callback, create) { // Rename to objectValue later | |
// small change to allow paths like 'a[0].c.d[3][4].e' which is the same as a.0.c.d.3.4.e | |
prop=prop.replace(/^\[([0-9]*)\]/g,'$1').replace(/\[([0-9]*)\]/g,'.$1'); // I still suck at regexp's ;P | |
var keys = prop.split('.'), | |
value, key; | |
for (var i = 0, end = keys.length - 1; i < end; i++) { | |
key = keys[i]; | |
value = obj[key]; | |
if (typeof value == "object" && value !== null) { | |
obj = value; | |
} else { | |
if (!create) { | |
if(callback!==undefined)callback(); | |
return; | |
} | |
obj[key] = {}; | |
obj = obj[key]; | |
} | |
} | |
key = keys[i]; | |
value = obj[key]; | |
if (obj.hasOwnProperty(key)){ | |
if (callback !== undefined) callback(value, obj, key); | |
return value; | |
} | |
else { | |
if (!create) { | |
callback(); | |
return; | |
} | |
obj[key] = null; | |
if (callback !== undefined) callback(obj[key], obj, key); | |
return null; | |
} | |
} | |
function objectMap(map, source, dest) { | |
dest = dest || {}; | |
objectIterate(map, function(path, obj, property) { | |
objectToPath(dest, path, function(destValue, destObject, destProp) { | |
objectToPath(source, obj[property], function(sourceValue, sourceObject) { | |
if(sourceObject)destObject[destProp] = sourceValue; | |
}) | |
}, true) | |
}); | |
return dest; | |
} | |
var _sourceValues = { | |
a: { | |
one: 1 | |
}, | |
b: { | |
c: { | |
two: 2 | |
} | |
}, | |
three: 3 | |
}; | |
var _map = { | |
one: 'a.one', | |
two: 'b.c.two', | |
three: 'three', | |
z: { | |
x: { | |
one: 'a.one.b' | |
} | |
} | |
}; | |
console.log(objectMap(_map, _sourceValues)); |
Sorry, only just noticed your comment.
I wouldnt mind doing, you got me interested in JSDOC.
Gonna be a bit. You made me decide I want to make the last object iterate I ever make and so I keep changing it.
Nearly there now tho, just wanna use that type checking you used and thinking of going the complete hog and checking for property on functions, regex, that sort of thing....if Im going complete, I may as well try to be complete ;P.
Even does normal looking paths now like a[9][1] sorta stuff. Ummmmd about using your syntax coz I quite like it, but decided on the usual, just coz its the usual.
Loving your stuff by the way.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hey!
Could you add some JSDOC style function comments? That will help me as I go to implement these. :)