0

I am wondering if there is a good way to get nodes within a deeply nested object to announce their position within the object.

For example, if you were to recursively crawl through the example data below (perhaps with help from a library like Lodash), is there a callback function you could pass to each node that would log the location.

Ideally, this would work at any point in the tree, not just leaf nodes.

i.e. announceLocation(data.b.d[2].j.k[1]) //=> ['b', 'd', '2', 'j', 'k', '1']

let data = {
    a: 1,
    b: {
        c: 2,
        d: [
            {
                e: 3,
                f: 4
            },
            {
                g: [5, 6, 7],
                h: 8,
                i: 9
            },
            {
                j: {
                    k: [10, 11, 12]
                }
            }
        ]
    },
    l: 13
}

UPDATE:

I haven't tried it out yet, but the npm library js-traverse has a contextual value called this.path that seems to be just what I'm looking for.

J. Munson
  • 2,275
  • 2
  • 17
  • 22
  • See if my answer to *How to enumerate complex javascript object* - https://stackoverflow.com/questions/49125398/how-to-enumerate-complex-javascript-object can help you. – Ori Drori Mar 13 '18 at 13:47
  • I don't think there is a generic way to do it unless all the values within the object structure are unique. – str Mar 13 '18 at 13:53
  • It seems like what you want is a reverse lookup for the path of the value. i.e., given the value, find the path to it. So something like a reverse map might work. https://stackoverflow.com/questions/26241478/reverse-lookup-object-with-array – Khauri Mar 13 '18 at 14:01

2 Answers2

0

JavaScript objects have no defined order, they are (by definition) an unsorted set of key-value pairs.

If however you want to sort the keys by some sorting algorithm you can use the following:

const sortedKeys = Object.keys(myObj).sort(sortingFunction);
Goran
  • 3,292
  • 2
  • 29
  • 32
  • 1
    How is the order relevant to the question? It is only about the nesting, not the order of siblings. – str Mar 13 '18 at 13:51
  • @Goran I don't disagree with anything you have said. However, the keys of an object still become part of the "path" to anything contained within the corresponding value. – J. Munson Mar 13 '18 at 14:03
  • 1
    In the provided example it is implicated that order is required: ['b', 'd', '2', 'j', 'k', '1'] - b and d are second and j and k are first in their objects. Also "their position within the object" - seems to me like sequential order, not nested level... But now I understand what you actually meant. – Goran Mar 13 '18 at 14:10
  • 1
    The value of "d" is an array. Therefore, the next item in the "path" after "d" should be an index. You are correct that order matters, but only when we've found ourselves inside an array. – J. Munson Mar 13 '18 at 14:14
0

You could insert a reference from the parent object into the child object. That way you always have a way of moving to the top of your object.

let groups = {
  '1': {
    'title': 'Group 1',
    'items': {}
  }
};
let items = [{ 'group_id': '1', 'id': '1', 'title': 'Item 1' }];

for(let item of items){
  item.parent = groups[item.group_id];
  groups[item.group_id].items[item.id] = item;
}


console.log(groups['1'].items['1']); // take a look at the parent property
enf0rcer
  • 545
  • 2
  • 11