1

I want to return the absolute path in a given object to a specific value.

In the following

A {
  a:1,
  b:2,
  c: {
    1:d,
    2:e
  }
  }

I want to grab 'e' and return it as 'A.c.2' (or any other format that gets this point across using JavaScript).

I'm not sure whether I should first stringify the object or not.

Essentially I'm just searching for given values 'searchobj(val)' and attempting to return each path where the corresponding value can be found for later use.

Please no Jquery.

2
  • That was meant to say no jquery. Commented Oct 2, 2015 at 4:20
  • Technically that's not required. From the tag info at stackoverflow.com/tags/javascript/info: Unless a tag for a framework or library is also included, a pure JavaScript answer is expected for questions with the javascript tag. Commented Oct 2, 2015 at 4:24

2 Answers 2

4

Here's a recursive function I made, that searches through the object and return the path as a.b.c

var obj = {
   "a": {
      "b": {
         "c": {
            1: 6
         }
      }
   },
   "d": {
      "e": 7
   },
   "h": {
      "g": 7
   },
   "arr": {
      "t": [22, 23, 24, 6]
   }

};

This will return the first path that is matched as a string.

var getObjectPath = function(search, obj) {

    var res = false;

    for (var key in obj) {
        if (obj.hasOwnProperty(key)) {
            if (typeof obj[key] == "object") { //If value is an object, call getObjectPath again!
                if (res = getObjectPath(search, obj[key])) {
                    res = key + "." + res;
                    return res; 
                }
            } else if (search === obj[key]) {
                return key; //Value found!
            }
        }
    }

    return res;
}
console.log(getObjectPath(7, obj)); //d.e
console.log(getObjectPath(6, obj)); //a.b.c.1
console.log(getObjectPath(24, obj)); //arr.t.2 //2 is the index

Multiple matches search, will return an array of paths

var getObjectPathMultiple = function(search, obj, recursion) {

    var res = false;
    var paths = [];

    for (var key in obj) {
        if (obj.hasOwnProperty(key)) {
            if (typeof obj[key] == "object") {
                if (res = getObjectPathMultiple(search, obj[key], true)) {
                    res = key + "." + res;
                    if (!recursion)
                        paths.push(res);
                    else return res;
                }
            } else if (search === obj[key]) {
                return key;
            }
        }
    }
    return recursion ? res : paths;
}
console.log(getObjectPathMultiple(7, obj)); //["d.e", "h.g"]
console.log(getObjectPathMultiple(6, obj)); //["a.b.c.1", "arr.t.3"]
console.log(getObjectPathMultiple(24, obj)); //["arr.t.2"]
Sign up to request clarification or add additional context in comments.

7 Comments

I had considered that approach but it doesn't take into account nested objects. and when a slight modification is in place it seems like I lsoe ref to the parent as well.
It does take into account nested object?, my example is a nested object. Please show me which object are you talking about, so I can test and give you another answer. a is an object inside an object, b is an object inside a, c is an object inside b, that's a nested object.
I had misread something. Is there a way you can account for a value being in an array in this solution? such if e:[2,3,7] would print d.e.[3] or d.e[3] or d.e.3?
personally, I'd change if (search == obj[key]) to if (search === obj[key]) - otherwise searching for anything false-like may return a false positive
@AndrewMata I added another function that return all the matches!
|
1

This should return paths that are "valid" javascript syntax

var A = {
    a:1,
    'b x':2,
    c: {
        1:'d',
        2:'e',
        3: 2
    },
    arr: [1,2,3,4]
};
var getObjectPaths= function(search, obj, root) {
    var paths = [];
    var getObjectPath = function(obj, path) {
        Object.keys(obj).forEach(function(key) {
            var thisPath = path;
            if(isNaN(key) && !/[^a-z$0-9_]/.test(key)) {
                thisPath += '.' + key;
            } else {
                thisPath += '["' + key + '"]';
            }
            if (search === obj[key]) {
                paths.push(thisPath);
            }
            else if (typeof obj[key] == "object") { //If value is an object, call getObjectPath again!
                getObjectPath(obj[key], thisPath)
            }
        });
    }
    getObjectPath(obj, root);
    return paths;
}

Sample run:

>>> getObjectPaths(2, A, 'A');
[ "A["b x"]", "A.c["3"]", "A.arr["1"]" ]

2 Comments

Anyway to do without needing to set a root? So that it doesn't need a root supplied but will rather just print the path starting without the root?
If seems that when using obj[key].match(re) it does not return the final[1] but ommits it. is there a possible workaround? I switched search == out

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.