Reputation: 11
const obj = {
first: { second: { third: 'done'} },
hello: { world: { foo: { bar: 'wrong' } } },
second: { third: 'wrong'}
};
const arr = [ 'first', 'second', 'third' ];
function traverse(obj, arr) {
}
// output = 'done'
Given a first input as a nested object, and a second input as an array containing strings, what is the best way to traverse the nested object based on the path set by the array to output done
?
Upvotes: 1
Views: 825
Reputation: 2661
if you want it short and to handle system file path like :
it returns the object if exist and -1 if not
const obj = {
first: { second: { third: 'done'} },
hello: { world: { foo: { bar: 'wrong' } } },
second: { third: 'wrong'}
};
function traverse(obj, path) {
let seq = path.split('/').filter(x => x != '');
seq.map( s => obj = !obj[s] ? -1 : obj[s] );
return obj;
}
console.log(traverse(obj, '/hello/notexist/'));
console.log(traverse(obj, '/hello/world/'));
or even shorter with a reduce()
instead of a map()
:
function traverse(obj, path) {
let seq = path.split('/').filter(x => x != '');
return seq.reduce((acc, curr) => !acc[curr] ? -1 : acc[curr], obj);
}
or a even even shorter :
function traverse(obj, path) {
return path
.split('/')
.filter(Boolean)
.reduce((acc, curr) => acc[curr] ? acc[curr] : -1, obj);
}
const obj = {
first: { second: { third: 'done'} },
hello: { world: { foo: { bar: 'wrong' } } },
second: { third: 'wrong'}
};
const res = traverse(obj, '/hello/world/'); // return {foo:...}
console.log(res);
Upvotes: 0
Reputation: 12990
You can reduce
the array arr
, changing the accumulator to a deeper object at each step.
const obj = {
first: { second: { third: 'done'} },
hello: { world: { foo: { bar: 'wrong' } } },
second: { third: 'wrong'}
};
const arr = [ 'first', 'second', 'third' ];
function traverse(obj, arr) {
return arr.reduce((acc, curr) => acc ? acc[curr] : undefined, obj);
}
console.log(traverse(obj, arr));
console.log(traverse(obj, ['hello', 'world', 'foo']));
console.log(traverse(obj, ['first', 'hello', 'world']));
Upvotes: 2
Reputation: 37755
You can use references
ref[key]
is an object, change ref
to ref[key]
Not Found
ref
has property name same as last
variable then return ref[last]
else return Not Found
const obj = { first: { second: { third: 'done'} },hello: { world: { foo: { bar: 'wrong' } } },second: { third: 'wrong'}};
const arr = [ 'first', 'second', 'third' ];
function traverse(obj, arr) {
let ref = obj
let last = arr[arr.length-1]
for(let i=0; i<arr.length-1; i++){
let key = arr[i]
if(typeof ref[key] === 'object'){
ref = ref[key]
} else{
return "Not found"
}
}
return ref.hasOwnProperty(last) ? ref[last] : "Not found"
}
console.log(traverse(obj,arr))
console.log(traverse(obj,['first','third']))
console.log(traverse(obj,['hello','world']))
Upvotes: 0