Skip to content

Recursive counting in arbitrary nested object

I’m attempting to do some data visualization and dealing with this dataset. Object with arbitrary nested objects. I’m trying to count how many times different values appear in a key. This is just a snippet of the dataset, in the original the owns nested objects go 7+ levels deep.

Example dataset I’m working with:

var companyData = [{
    company: 'Pepsico',
    type: 'parent',
    owns: [
      {
      company: 'Cheetos',
      type: 'chips',
      owns: [{
        company: 'CheezyChipCo',
        type: 'chips',
        owns: []
      }]
      },
      {
        company: 'Gatorade',
        type: 'drink',
        owns: [{
          company: 'Powerade',
          type: 'drink',
          owns: []
        }]
        },
    ],
  }];

I’m thinking I’ll have to do a Recursion or a Flatten type operation. So I can put all the type values into an array like this.

What I’m trying to achieve:

[ 'drink', 'drink', 'chips', 'chips', 'parent' ]

I need to open up owns so I can properly count the type values. I feel like there are two ways I can go about it. Either recursion to go deep into an object. OR flatten the objects, so that all the nests are on the same level. I’ll probably use Object[keys] in combination with .filter, .some, or .reduce. But I am so stumped on how and in what order, and would love some help! Here’s my psuedo:

  1. if (type of object’s key is an Object)
  2. && if (object’s key === “type”)
  3. then push that type.value to an array
  4. else if (type of object’s key !=== object)
  5. then just return the new sorted array

Sorry, real frontend dev hours. I don’t know if that made sense and if posting all my failed code attempts would help.

Answer

Using straightforward recursion…

var companyData = [{ company: 'Pepsico', type: 'parent', owns: [{ company: 'Cheetos', type: 'chips', owns: [{ company: 'CheezyChipCo', type: 'chips', owns: [] }] }, { company: 'Gatorade', type: 'drink', owns: [{ company: 'Powerade', type: 'drink', owns: [] }] },], }];

function mapTypes(arr, acc = []) {
  for (const o of arr) {
    acc.push(o.type);
    if (o.owns.length > 0) {
      acc = mapTypes(o.owns, acc)
    }
  }
  return acc;
}

console.log(mapTypes(companyData));