Thiago Macedo
Thiago Macedo

Reputation: 13

how to get the path of an object's value from a value in javascript

Example:

var someObject = {
'part1' : {
    'name': 'Part 1',
    'txt': 'example',
},
'part2' : {
    'name': 'Part 2',
    'size': '15',
    'qty' : '60'
},
'part3' : [
    {
        'name': 'Part 3A',
        'size': '10',
        'qty' : '20'
    }, {
        'name': '[value]',
        'size': '5',
        'qty' : '20'
    }, {
        'name': 'Part 3C',
        'size': '7.5',
        'qty' : '20'
    }
]};

I need a function to get the path of the object to the value "[value]" which can be anywhere on the object

This object will be passed by the User, for this reason I will not know the structure of it.

something like:

getPath(obj, '[value]');

Upvotes: 1

Views: 2927

Answers (3)

Tarwin Stroh-Spijer
Tarwin Stroh-Spijer

Reputation: 353

If you try this on the window object you'll end up in trouble as it is self referential. Quick and easy way to get around this is to a depth check:

  function getPath(obj, val, path, depth) {
     if (!depth) depth = 0;
     if (depth > 50) return '';
     path = path || "";
     var fullpath = "";
     for (var b in obj) {
        if (obj[b] === val) {
           return (path + "/" + b);
        }
        else if (typeof obj[b] === "object") {
           fullpath = getPath(obj[b], val, path + "/" + b, depth++) || fullpath;
        }
     }
     return fullpath;
  }

This will return the same kind of path as above:

/part3/2/qty

To make that into an actual reference to variable simply regex:

'window' + '/part3/2/qty'.replace(/\/([0-9]+)\//g, '[$1].').replace(/\//g, '.')

Upvotes: 0

zero298
zero298

Reputation: 26878

Here's some code that should get you a path to your object, not sure how super safe it is:

function getPath(obj, val, path) {
   path = path || "";
   var fullpath = "";
   for (var b in obj) {
      if (obj[b] === val) {
         return (path + "/" + b);
      }
      else if (typeof obj[b] === "object") {
         fullpath = getPath(obj[b], val, path + "/" + b) || fullpath;
      }
   }
   return fullpath;
}

Where testObj is the object in your example:

console.log(getPath(testObj, '20'));      // Prints: /part3/2/qty
console.log(getPath(testObj, "[value]")); // Prints: /part3/1/name

Upvotes: 2

Konstantin Krass
Konstantin Krass

Reputation: 8646

Try this:

http://jsfiddle.net/n8d2s/1/

The method returns an object, that contains the parts.

function getPath(obj, value, path){
    path = path || [];   
    if(obj instanceof Array || obj instanceof Object){
        //Search within children
        for(var i in obj){
           path.push(i); //push path, will be pop() if no found
            var subPath = getPath(obj[i], value, path);
            //We found nothing in children
            if(subPath instanceof Array){
                if(subPath.length == 1 && subPath[0]==i){
                  path.pop();   
                }
            //We found something in children
            }else if(subPath instanceof Object){
               path = subPath;                
               break;   
            }
        }
    }else{
        //Match ?
        if(obj == value){            
            return {finalPath:path};   
        }else{
            //not ->backtrack
            path.pop();
            return false;   
        }
    } 
    return path;
}

Maybe its not the best code, took me 10min there but it should work.

To see any result, check your dev console F12.

Upvotes: 0

Related Questions