Home > database >  Tallying the occurrence of an object value that is generic nested in React
Tallying the occurrence of an object value that is generic nested in React

Time:07-11

I have a JSON object that looks like this, I'm trying to write a function that would take the object as an input, then output the occurrence of each status value in an object array: i.e. [ERROR: 2, WARNING: 3, OK: 2]. The problem is that I don't know how to access and count the values when 'status' is nested under different layers.

const data = {
        "item1": {
            "item1.1": {
                "item1.1.1": {
                    "item1.1.1.1": {
                        "attr1": [],
                        "attr2": "",
                        "attr3": [],
                        "status" : "ERROR"
                    }
                }
            },
            "item1.2": {
                "item1.2.1": {
                    "item1.2.1.1": {
                        "attr1": [],
                        "attr2": "",
                        "attr3": [],
                        "status" : "WARNING"
                    }
                }
            }
        },
        "item2": {
            "item2.1": {
                "item2.1.1": {
                    "item2.1.1.1": {
                        "attr1": [],
                        "attr2": "",
                        "attr3": [],
                        "status" : "WARNING"
                    }
                },
                "item2.1.2": {
                    "item2.1.2.1": {
                        "attr1": [],
                        "attr2": "",
                        "attr3": [],
                        "status" : "OK"
                    },
                    "item2.1.2.2": {
                        "attr1": [],
                        "attr2": "",
                        "attr3": [],
                        "status" : "WARNING"
                    }
                }
            }
        },
        "item3": {
            "item3.1": {
                "item3.1.1": {
                    "item3.1.1.1": {
                        "attr1": [],
                        "attr2": "",
                        "attr3": [],
                        "status" : "OK"
                    }
                },
                "item3.1.2": {
                    "attr1": [],
                    "attr2": "",
                    "attr3": [],
                    "status" : "ERROR"
                }
            }
        }

    }

This is the function I'm trying to modify to achieve what I want, it only works when 'obj' is a parent of an object with the 'status' key

 function getTally (obj) {
        const tally = Object.values(obj).reduce(function (acc, folder) {
            if (!acc[folder.status]) {
                acc[folder.status] = 1;
            } else {
                acc[folder.status]  ;
            }
            return acc;
        }, {});
        console.log(obj)
        console.log(tally)

CodePudding user response:

This kind of problem I used to use some recursion (when possible). You need some way to visit the nested objects. That is why I believe to solve this problem with recursion.

for examle:

function getStatus(obj, results) {
  if (obj.status) {
    results[obj.status]  = 1;
  }

  Object.entries(obj).forEach(([, value]) => {
    if (value !== null && !Array.isArray(value) && typeof value === 'object') {
      getStatus(value, results);
    }
  });

  return results;
}

const res = getStatus(data, {
  ERROR: 0,
  WARNING: 0,
  OK: 0,
});

As you are passing an accumulator you only need return at the end of the recursion. When the object being visited do not have more values to be vistied the recursion starts to return and at the end it returns the accumulator data.

Note that the function is not visiting nested arrays.

  • Related