0

Let's say I've got the following javascript object

var obj = {
            a:{
                b:"value",
                c:{
                    d:"value2"
                }
            }
        }

What function would, when input with the "d" object (for example, function getPath(obj, d)), output the "a.c.d" string? I've tried various things including object-path, but it doesn't seem to be designed for that

7
  • 4
    Can you elaborate on "input with the "d" object"? Please provide an example of such a function call. If you mean something like path(obj.a.c.d), then there is no way to get the desired outcome (because all the function gets is the string value "value2", it doesn't, and cannot, know about obj). Commented Jun 6, 2017 at 16:53
  • 2
    What are you trying to achieve with that? What if another property had a child 'd'? What if a parent is a 'd'? Commented Jun 6, 2017 at 16:53
  • 1
    How would this react to obj = {d:{d:{d:{d:"val"}}}} when asked for d? does it return d, d.d, d.d.d or d.d.d.d? Commented Jun 6, 2017 at 16:55
  • @NickA It should return d.d.d.d @Felix Kling Would it not be possible if you also input "obj"? Commented Jun 6, 2017 at 16:56
  • 1
    Possible duplicate of Return path to value in JavaScript object Commented Jun 6, 2017 at 17:01

4 Answers 4

3

You could use an iterative and recursive approach.

function getPath(object, key) {

    function iter(o, p) {
        if (typeof o === 'object') {
            return Object.keys(o).some(function (k) {
                return iter(o[k], p.concat(k));
            });
        }
        if (p[p.length - 1] === key) {
            path = p;
            return true;
        }
    }

    var path = [];
    iter(object, []);
    return path.join('.');
}

console.log(getPath({ d: { d: { d: { d: 'val' } } } }, 'd'));
console.log(getPath({ a: { b: 'value', c: { d: 'value2' } } }, 'd'));
.as-console-wrapper { max-height: 100% !important; top: 0; }

Sign up to request clarification or add additional context in comments.

Comments

1

I had a fair amount of fun making this one up, it generates a list of every possible path that can be made from the object and returns the longest one ending with the correct key, it returns an empty string of not found:

function getPath(obj, key) {
    paths = []

    function getPaths(obj, path) {
        if (obj instanceof Object && !(obj instanceof Array)) {
            for (var k in obj){
                paths.push(path + "." + k)
                getPaths(obj[k], path + "." + k)
            }
        }
    }

    getPaths(obj, "")
    return paths.map(function(p) {
        return p.slice(p.lastIndexOf(".") + 1) == key ? p.slice(1) : ''
    }).sort(function(a, b) {return b.split(".").length - a.split(".").length;})[0];
}

var obj = { a:{ b:"value", c:{ d:"value2"}}};
console.log(getPath(obj, "b"))
console.log(getPath(obj, "c"))
console.log(getPath(obj, "d"))

var obj = { d:{ d:"value", d:{ d:"value2"}}};
console.log(getPath(obj, "d"))

Comments

0

You can iterate over the object using a recursive function, and save the path like :

function getPath(object, keyValue, path) {
  for (var k in object) {
    if (k === keyValue) {
      return path + '.' + k;
    }
    else if (typeof object[k] === 'object') {
      return getPath(object[k], keyValue, path !== '' ? path + '.' + k : k);
    }
  }
}

var obj = {
    a:{
        b:"value",
        c:{
            d:"value2"
        }
    }
};

var path = getPath(obj, 'd', '');
console.log(path);

1 Comment

Does not work for test case obj = {d:{d:{d:{d:"val"}}}}
0

Here you go. The function you want to use is findLongestPath:

var obj = {
    a:{
        b:"value",
        c:{
            d:"value2"
        }
    }
};

function findAllPaths(obj, property, startString = '') {
  var pathStrings = [];
  Object.keys(obj).forEach(key => {
    if(typeof obj[key] === 'object') {
      pathStrings.push(...findAllPaths(obj[key], property, startString + key + '.'));
      return;
    }
    
    pathStrings.push(startString + key);
  });
  
  return pathStrings;
}

function findLongestPath(obj, property) {
  return findAllPaths(obj, property)
    .filter(str => str.split('').reverse().join('').slice(0, property.length) === property.split('').reverse().join(''))
    .reduce((longest, next) => longest.length >= next.length ? longest : next, '');
}

console.log(findLongestPath(obj, 'd'));

findAllPaths is a recursive function that iterates through the object and generates an array of all possible object paths. findLongestPath filters those strings to make sure the last property matches the property given, and then returns the longest of those.

1 Comment

Note that this will break if one of the properties is anything other than an object or a string.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.