I have this:
{ 'Payment' : {
'Referenced' : 'referenced payment',
'Conciliate' : 'conciliate payment',
'Multiple' : 'multiple payment'
}
}
but can change in all moment for random nodes or add more, like:
{ 'Payment' : {
'Referenced' : 'referenced payment',
'Conciliate' : 'conciliate payment',
'Multiple' : {
'mult1' : 'example1',
'mult2' : 'example1'
},
'Inventory' : {
'datastorage' : 'dt1'
}
}
All nodes can be asigned randomly, and I need to search by value, I can pass:
referenced payment
and need:
Payment/Referenced
or I send:
example1
and I need:
Payment/Multiple/mult1
I don't know if exist something like that.
CodePudding user response:
// Function
const findPath = (obj, query) => {
const makeArray = (obj, path = []) => {
const pairs = Object.entries(obj);
return pairs.map(([key, value]) =>
typeof value === "object"
? makeArray(value, [...path, key])
: { path: [...path, key], value }
);
};
return (
makeArray(obj)
.flat(Infinity)
.find(({ path, value }) => value === query)?.path.join("/") ?? null
);
};
// Usage
const path1 = findPath(
{
Payment: {
Referenced: "referenced payment",
Conciliate: "conciliate payment",
Multiple: {
mult1: "example1",
mult2: {
test: 123,
},
},
Inventory: {
datastorage: "dt1",
},
},
},
123
);
const path2 = findPath(
{
Payment: {
Referenced: "referenced payment",
Conciliate: "conciliate payment",
Multiple: {
mult1: "example1",
},
Inventory: {
datastorage: "dt1",
},
},
},
"referenced payment"
);
console.log("123: " path1);
console.log("referenced payment: " path2);
Explanation
The first step is converting the object into a linear array of the object tree and its paths. This is done recursively. Then, the array is flattened in order to be iterated through with Array.prototype.find
, if the value matches the query, the path is returned, if no match was found it returns null
.
Credits
Thanks to @Bravo for suggesting path array instead of template literal