Risograph
Risograph

Reputation: 13

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.

Upvotes: 1

Views: 928

Answers (3)

pilchard
pilchard

Reputation: 12918

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));

Upvotes: 1

HichamELBSI
HichamELBSI

Reputation: 1719

Here is my solution. You can do it with a reduce function.

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: []
        }]
        },
    ],
  }];

    let arr = []
const formattedData = (data) => data.reduce((acc, curr) => {
   arr.push(curr.type);
  
  if (Array.isArray(curr.owns)) {
    formattedData(curr.owns)
  }
  
  return arr;
  
}, []);
  
 console.log(formattedData(companyData))

Upvotes: 0

Mulan
Mulan

Reputation: 135357

You can write a simple recursive flatten -

const flatten = ({ type, owns = [] }) =>
  [ type, ...owns.flatMap(flatten) ]
 
const input =
  [{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:[]}]}]}]
 
console.log(input.flatMap(flatten))

[
  "parent",
  "chips",
  "chips",
  "drink",
  "drink"
]

Upvotes: 1

Related Questions