I've been using lodash for a while now and I really love the _.set
and _.get
methods.
I'm trying to solve a problem to get the deep key paths whose final value is a string, but when I'm too dumb for it. Spend 3 hours on it and can't find a perfect solution:
const myObject = {
a: 'myObject.a',
b: {
ba: 'myObject.b.ba',
bb: ['myObject.b.bb[0]'],
},
c: [
{ ca: 'myObject.c[0].ca' },
],
};
So I have myObject
(that's far more nested in real life) and I want to get paths to the values, but only the final one.
The method would look like getDeepPaths(myObject)
and would return in this case: ['myObject.a', 'myObject.b.ba', 'myObject.b.bb[0]', 'myObject.c[0].ca' ]
Did anyone solve something like this before?
Recursion is actually not that hard. Here's how you could solve this problem:
const myObject = {
a: 'myObject.a',
b: {
ba: 'myObject.b.ba',
bb: ['myObject.b.bb[0]'],
},
c: [
{ ca: 'myObject.c[0].ca' },
],
};
var stringLeaves = function(path, obj) {
if (typeof obj === 'string') {
return [path]
}
return Object.keys(obj)
.filter(k => obj.hasOwnProperty(k))
.map(k => stringLeaves(path + '.' + k, obj[k]))
.reduce((a,x) => a.concat(x), []); // this line flattens the array
};
console.log(stringLeaves('myObject', myObject));
The work is done by the stringLeaves
function. In this function:
obj
passed in as a parameter is a string, then just return the current path.stringLeaves
recursively, by passing in the adjusted path (current path + the new property name) and the object/value that resides at that particular key.The convention of the function is that it returns an array of all possible matches. This is why:
.reduce((a,x) => a.concat(x), []);
line: to transform an array of arrays into one array that consists of all the values present in the original arrays.Note that the function cannot deduce that your object is called myObject
, so I passed that name as an initial path.