Pedro Henrique Pedro Henrique - 1 month ago 8
Javascript Question

filter array recursively looking for parents

I have an array like that:

[
{"id":"one","name":"school", "selected": false, "childs":[
{"id":"1","name":"school", "selected": false},
{"id":"2","name":"student", "selected": true},
{"id":"3","name":"teacher", "selected": false}
]},
{"name":"two","name":"school", "selected": false, "childs":[
{"id":"1","name":"school", "selected": true},
{"id":"3","name":"teacher", "selected": false}
]},
{"name":"three","name":"school", "selected": true, "childs":[
{"id":"1","name":"school", "selected": false},
{"id":"2","name":"student", "selected": false}
]}
]


How I can filter on that array to get only the name of the object that has the field select as true?

The output should be an array for the name of objects:

[student, school, school]


I tried this using lodash:

_.filter(array, {selected: true}).map(function (division) {
return array.name;
});


But this always return the root objects, never the objects that are inside the childs.

Answer

You could just iterate and look if the wanted property selected is true, the push to result, if there is a children, iterate the children.

This works with Array#forEach

var data = [{ "id": "one", "name": "school", "selected": false, "children": [{ "id": "1", "name": "school", "selected": false }, { "id": "2", "name": "student", "selected": true }, { "id": "3", "name": "teacher", "selected": false }] }, { "name": "two", "name": "school", "selected": false, "children": [{ "id": "1", "name": "school", "selected": true }, { "id": "3", "name": "teacher", "selected": false }] }, { "name": "three", "name": "school", "selected": true, "children": [{ "id": "1", "name": "school", "selected": false }, { "id": "2", "name": "student", "selected": false }] }],
    result = [];

data.forEach(function iter(o) {
    o.selected && result.push(o.name);
    (o.children || []).forEach(iter);
});
  
console.log(result);

The same with lodash _.forEach

var data = [{ "id": "one", "name": "school", "selected": false, "children": [{ "id": "1", "name": "school", "selected": false }, { "id": "2", "name": "student", "selected": true }, { "id": "3", "name": "teacher", "selected": false }] }, { "name": "two", "name": "school", "selected": false, "children": [{ "id": "1", "name": "school", "selected": true }, { "id": "3", "name": "teacher", "selected": false }] }, { "name": "three", "name": "school", "selected": true, "children": [{ "id": "1", "name": "school", "selected": false }, { "id": "2", "name": "student", "selected": false }] }],
    result = [];

_.forEach(data, function iter(o) {
    o.selected && result.push(o.name);
    _.forEach(o.children, iter);
});
  
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.min.js"></script>

A version with Array#reduce.

var data = [{ "id": "one", "name": "school", "selected": false, "children": [{ "id": "1", "name": "school", "selected": false }, { "id": "2", "name": "student", "selected": true }, { "id": "3", "name": "teacher", "selected": false }] }, { "name": "two", "name": "school", "selected": false, "children": [{ "id": "1", "name": "school", "selected": true }, { "id": "3", "name": "teacher", "selected": false }] }, { "name": "three", "name": "school", "selected": true, "children": [{ "id": "1", "name": "school", "selected": false }, { "id": "2", "name": "student", "selected": false }] }],
    result = data.reduce(function iter(r, o) {
        o.selected && r.push(o.name);
        return (o.children || []).reduce(iter, r);
    }, []);
  
console.log(result);

And another version with lodash _.reduce.

var data = [{ "id": "one", "name": "school", "selected": false, "children": [{ "id": "1", "name": "school", "selected": false }, { "id": "2", "name": "student", "selected": true }, { "id": "3", "name": "teacher", "selected": false }] }, { "name": "two", "name": "school", "selected": false, "children": [{ "id": "1", "name": "school", "selected": true }, { "id": "3", "name": "teacher", "selected": false }] }, { "name": "three", "name": "school", "selected": true, "children": [{ "id": "1", "name": "school", "selected": false }, { "id": "2", "name": "student", "selected": false }] }],
    result = _.reduce(data, function iter(r, o) {
        o.selected && r.push(o.name);
        return _.reduce(o.children, iter, r);
    }, []);
  
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.min.js"></script>