Skip to content

Instantly share code, notes, and snippets.

@killants
Last active November 10, 2022 04:34
Show Gist options
  • Save killants/569c4af5f2983e340512916e15a48ac0 to your computer and use it in GitHub Desktop.
Save killants/569c4af5f2983e340512916e15a48ac0 to your computer and use it in GitHub Desktop.
Sharing knowledge
/**
* searches deep into an object recursively...
* @param {Object} obj object to be searched
* @param {any} searchValue the value/key to search for
* @param {Object} [options]
* @param {boolean} options.[searchKeys] whether to search object keys as well as values. Defaults to `true` if `serchValue` is a string, `false` otherwise.
* @param {number} options.[maxDepth=20] maximum recursion depth (to avoid "Maximum call stack size exceeded")
* @returns {string[]} Paths on the object to the matching results
*/
const findPaths = (
obj,
searchValue,
{ searchKeys = typeof searchValue === "string", maxDepth = 20 } = {}
) => {
const paths = []
const notObject = typeof searchValue !== "object"
const gvpio = (obj, maxDepth, prefix) => {
if (!maxDepth) return
for (const [curr, currElem] of Object.entries(obj)) {
if (searchKeys && curr === searchValue) {
// To search for property name too ...
paths.push(prefix + curr)
}
if (typeof currElem === "object") {
// object is "object" and "array" is also in the eyes of "typeof"
// search again :D
gvpio(currElem, maxDepth - 1, prefix + curr + "/")
if (notObject) continue
}
// it's something else... probably the value we are looking for
// compares with "searchValue"
if (currElem === searchValue) {
// return index AND/OR property name
paths.push(prefix + curr)
}
}
}
gvpio(obj, maxDepth, "")
return paths
}
// Big thanks to "https://dev.to/qm3ster"
/*
To search an object for a value
- searches deep into the object using recursive...
RETURN : array with paths on the object to the matching results
--------------------------------------------------------------------------------------------------------------------
obj -> to object to be searched
searchValue -> the value to search
bCompareValuesOnly -> boolean indication to compare values only OR to compare also the properties name ....
maxDeepLevel -> the maximun level this recursive function can get ( to avoid "Maximum call stack size exceeded" )
currDeepLevel -> IGNORE THIS PARAMETER : it's used by the function itself to control deep level
*/
function getValuePathInObject(obj, searchValue, bCompareValuesOnly, maxDeepLevel, currDeepLevel){
var bShowInfo = false ;
maxDeepLevel = ( maxDeepLevel || maxDeepLevel == 0 ) ? maxDeepLevel : 20;
currDeepLevel = currDeepLevel ? currDeepLevel : 1 ;
if( currDeepLevel > maxDeepLevel ){
return [];
} else {
var charSeparator = "/";
var paths = [];
var i=0;
for(var curr in obj){
var currElem = obj[curr];
if( currDeepLevel == 1 && bShowInfo ){
console.log("getValuePathInObject_> Looking property \"" + curr + "\" ");
}
if( !bCompareValuesOnly && curr === searchValue ){// To search for property name too ...
paths.push( curr );
}
if( typeof currElem == "object" ){ // object is "object" and "array" is also in the eyes of "typeof"
// search again :D
var deepPaths = getValuePathInObject( currElem, searchValue, bCompareValuesOnly, maxDeepLevel, currDeepLevel + 1 );
for(var e=0 ; e<deepPaths.length ; e++){
paths.push( curr + charSeparator + deepPaths[e]);
}
} else { // it's something else ... problably the value we are looking for
// compares with "searchValue"
if(currElem === searchValue ){
// return index AND/OR property name
paths.push( curr );
}
}
i++;
}
return paths;
}
}
@nicolapiccinelli
Copy link

findPaths.js:18 you should also check for null or undefined values

@killants
Copy link
Author

findPaths.js:18 you should also check for null or undefined values

Thanks for the feedback.
I didn't add that validation since i may want to search for "null" values in the object and get the path of those cases.

Regarts

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment