I have an array like that:
[
{"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}
]}
]
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 children.
I have an array like that:
[
{"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}
]}
]
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 children.
Share Improve this question edited Oct 12, 2016 at 19:14 Pedro Henrique asked Oct 12, 2016 at 18:17 Pedro HenriquePedro Henrique 6392 gold badges9 silver badges27 bronze badges 3- You could use a basic for loop – Nick Tucci Commented Oct 12, 2016 at 18:23
- 1 Just a note: children is the plural of child. – sabithpocker Commented Oct 12, 2016 at 18:35
- @sabithpocker Or chilrens – guest271314 Commented Oct 12, 2016 at 19:05
7 Answers
Reset to default 4You 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./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./ajax/libs/lodash.js/4.15.0/lodash.min.js"></script>
array
.reduce((a, i) => [...a, i, ...i.childs], [])//flatten array
.filter(i => i.selected)//filter with selected===true
.map(i => i.name));//map to name
console.log([{
"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
}]
}].reduce((a, i) => [...a, i, ...i.childs], []).filter(i => i.selected).map(i => i.name));
You could use this functional programming style ES6 solution:
function sel(array) {
return (array || []).reduce ( (acc, o) =>
(o.selected ? acc.concat(o.name) : acc).concat(sel(o.childs)), [] );
}
function sel(array) {
return (array || []).reduce ( (acc, o) =>
(o.selected ? acc.concat(o.name) : acc).concat(sel(o.childs)), [] );
}
// Sample data
var array = [
{"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}
]}
];
// Extract
var result = sel(array);
// Ooutput result
console.log(result);
You can use Array.prototype.map()
, Array.prototype.filter()
var arr = [{
"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
}]
}];
var res = arr.map(el =>
(el.selected && el || el.childs.filter(child =>
child.selected
)[0]).name
);
console.log(res);
Well, you should consider the plexity of the script you are trying to build. This is a nested linear algorithm (see https://en.wikipedia/wiki/Linear_search) since you have to touch every single element in the array to create the new data structure with the selected
elements, which can be very slow if that array size increases.
What you might want to do instead, is to modify the method that toggles the selected
property, and copy that 'selected' object to a new selectedElements
array.
However, if you are required to do what you asked, and you only want UNIQUE results, check this out:
var data = [
{"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}
]}
],
selectedElements = [];
data.map(function(row, i){
if (row.selected) {
if (selectedElements.indexOf(row.name) == - 1)
selectedElements.push(row.name);
}
else{
row.childs.map(function(childRow, ii) {
if (childRow.selected) {
if (selectedElements.indexOf(childRow.name) == - 1)
selectedElements.push(childRow.name);
}
})
}
});
console.log(selectedElements);
Add a line before your lodash _.filter
array = _.flatten(array.map(x => [x].concat(x.childs)))
so it will take the childs
.
A classic recursive solution with arrow functions
var result = [];
var recursiveSearch = arr => {
if (Array.isArray(arr)) {
arr.forEach(x => {
if (x.selected === true) result.push(x.name);
if (Array.isArray(x.childs)) recursiveSearch(x.childs);
});
}
}
recursiveSearch(data);
console.log (result);