Last active
March 29, 2024 03:11
-
-
Save ryanmorr/c750659b2d82c372955e819774500c23 to your computer and use it in GitHub Desktop.
Get and set deeply nested object properties via paths
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
const has = {}.hasOwnProperty; | |
function getPath(root, tester, path = []) { | |
for (const key in root) { | |
if (has.call(root, key)) { | |
const value = root[key]; | |
if (tester(key, value) === true) { | |
path.push(key); | |
return path; | |
} | |
if (typeof value === 'object' && value !== null) { | |
const copy = path.slice().concat([key]); | |
const result = getPath(value, tester, copy); | |
if (result) { | |
return result; | |
} | |
} | |
} | |
} | |
} | |
function setPath(root, path, value) { | |
let obj = root; | |
const copy = path.slice(); | |
while(obj && copy.length > 0) { | |
const prop = copy.shift(); | |
if (copy.length === 0) { | |
obj[prop]= value; | |
} else { | |
obj = obj[prop]; | |
} | |
} | |
} | |
// Usage: | |
const obj = { | |
a: { | |
b: { | |
c: 10, | |
d: { | |
e: 20 | |
} | |
}, | |
f: { | |
g: 30, | |
h: 40, | |
i: { | |
j: 50 | |
}, | |
k: { | |
l: { | |
m: 60 | |
} | |
} | |
}, | |
n: { | |
o: 70 | |
} | |
}, | |
p: { | |
q: 80 | |
} | |
}; | |
// Provide a test function to get the path to the first property that satisfies a condition | |
const path = getPath(obj, (key, val) => val === 60); //=> ["a", "f", "k", "l", "m"] | |
console.log(obj.a.f.k.l.m); //=> 60 | |
// Set a new value for the property with the given path; | |
setPath(obj, path, 100); | |
console.log(obj.a.f.k.l.m); //=> 100 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment