3

I am trying to get the parent of a specific (referenced) object in an array. Example:

var data = [
    {
        key: "value1"
        children: [
            {
                key: "value2"
            },
            {
                key: "value3"
                children: [
                    {
                        key: "value3a"
                    },
                    {
                        key: "value3b"
                    }
                ]
            }
        ]
    },
    {
        key: "value4"
    }
];

When some stuff happens, I get the following:

var clicked = {
    key: "value3a"
}

In this case I know that value3a has been clicked, and it's databound with the data variable.

The question is, how do I easily get the parent of clicked? It should return the whole children-array of value3 which I want:

[
    {
        key: "value3a"
    },
    {
        key: "value3b"
    }
]

Note: currently I am using UnderscoreJS to find the object of my array. So maybe UnderscoreJS could help?

Jamiec
  • 133,658
  • 13
  • 134
  • 193
thomas479
  • 509
  • 1
  • 6
  • 17
  • Take a look on this example that demonstrates tree with click: http://stackoverflow.com/questions/19691917/how-do-display-a-collapsible-tree-in-angularjs-bootstrap/19692791#19692791 – Maxim Shoustin May 01 '15 at 10:56
  • possible duplicate of [Javascript objects: get parent](http://stackoverflow.com/questions/2980763/javascript-objects-get-parent) – JJJ May 01 '15 at 10:56
  • Have a look into the link http://stackoverflow.com/a/5154070/4373895 – VikrantMore May 01 '15 at 10:57

2 Answers2

0

Just create a child-parent map so that you can look up what you need:

var map = {};
function recurse(arr, parent) {
    if (!arr) return;
    for (var i=0; i<arr.length; i++) { // use underscore here if you find it simpler
        map[arr[i].key] = parent;
        recurse(arr[i].children, arr[i]);
    }
}
recurse(data, {key:"root", children:data});

Now, in your event handler you can trivially use that map to look up your siblings:

map[clicked.key].children
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
0

You could use a recursive reduce function.

// Given
var data = [
    {
        key: "value1",
        children: [
            {
                key: "value2"
            },
            {
                key: "value3",
                children: [
                    {
                        key: "value3a"
                    },
                    {
                        key: "value3b"
                    }
                ]
            }
        ]
    },
    {
        key: "value4"
    }
];
var clicked = {
    key: "value3a"
};

We can define a recursive reduce function, and give it the parent as the context.

var rec_reduce = function(memo, obj) {
    if(obj.key == clicked.key) {
        return this || memo;
    }
    return _.reduce(obj.children, rec_reduce, memo, obj.children) || memo;
};

// Now we can lookup the key in clicked with one line
_.reduce(data, rec_reduce, null, data);

// Returns [{key: "value3a"}, {key: "value3b"}]

Or, if you want to leverage underscore to make a map as suggested in the first answer, that is even simpler:

var map = {};
var rec_map = function(obj, i, parent) {
    map[obj.key] = parent;
    _.each(obj.children, rec_map);
};
_.each(data, rec_map);

// Now getting the parent list is just a look up in the map
map[clicked.key]

// Returns [{key: "value3a"}, {key: "value3b"}]
Brad Pitcher
  • 1,693
  • 17
  • 21