I have the following data stored in a variable:
let categories = [
{
name: "a",
selected: false,
nodes: [
{
name: "aa",
selected: false
},
{
name: "ab",
selected: true
},
{
name: "ac",
selected: true
},
{
name: "ad",
selected: false
}
]
},
{
name: "b",
selected: false,
nodes: [
{
name: "ba",
selected: false
},
{
name: "bb",
selected: true
},
{
name: "bc",
selected: true
},
{
name: "bd",
selected: false
}
]
}
];
I want to count how much item has selected = true
.
So I create the following function:
function getSelected(categories, counter = 0) {
for (let index = 0; index < categories.length; index++) {
const category = categories[index];
if (category.selected) {
counter++;
}
if (category.nodes && category.nodes.length) {
category.nodes.forEach(cat => getSelected([cat], counter));
}
}
return counter;
}
but it always returns 0 .
You could take a recursive reduce of the nodes and count selected
.
const countSelected = (s, o) => (o.nodes || []).reduce(countSelected, s + o.selected); let categories = [{ name: "a", selected: false, nodes: [{ name: "aa", selected: false }, { name: "ab", selected: true }, { name: "ac", selected: true }, { name: "ad", selected: false }] }, { name: "b", selected: false, nodes: [{ name: "ba", selected: false }, { name: "bb", selected: true }, { name: "bc", selected: true }, { name: "bd", selected: false }] }], count = categories.reduce(countSelected, 0); console.log(count);
It is because Number (and other primitives) arguments to function are duplicated, it create a whole new variable initialized with the arguments value.
what you can do is either use the return value of your function and sum it, or you can use Objects as arguments as they are send by reference, so you keep the same object :
let categories = [{name: "a",selected: false,nodes: [{name: "aa",selected: false},{name: "ab",selected: true},{name: "ac",selected: true},{name: "ad",selected: false}]},{name: "b",selected: false,nodes: [{name: "ba",selected: false},{name: "bb",selected: true},{name: "bc",selected: true},{name: "bd",selected: false}]}] function getSelectedWithObject(categories, counter = {val: 0}) { for (let index = 0; index < categories.length; index++) { const category = categories[index] if (category.selected) { counter.val++ } if (category.nodes && category.nodes.length) { category.nodes.forEach(cat => getSelectedWithObject([cat], counter)) } } return counter.val } function getSelectedWithReturnValue(categories) { let counter = 0 for (let index = 0; index < categories.length; index++) { const category = categories[index] if (category.selected) { counter++ } if (category.nodes && category.nodes.length) { category.nodes.forEach(cat => counter += getSelectedWithReturnValue([cat])) } } return counter } console.log(getSelectedWithObject(categories)) console.log(getSelectedWithReturnValue(categories))
counter
is an integer so it's passed by value here. Make the counter
the result you want to get back from the function and there you go:
function getSelected(categories) {
var counter = 0;
for (let index = 0; index < categories.length; index++) {
const category = categories[index];
if (category.selected) {
counter++;
}
if (category.nodes && category.nodes.length) {
category.nodes.forEach(cat => counter += getSelected([cat]));
}
}
return counter;
}
console.log(getSelected(categories));
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.