user4491521
user4491521

Reputation:

Recursively list nested object keys

i have an nested object as such:

  options = {
    religous: {
      kosher: {
        value: 'Kosher',
        chosen: false
      },
      halal: {
        value: 'Halal',
        active: false
      },
    },
    vegan: {
      value: 'Vegan',
      active: false
    }
  }

It contains nested objects of varying sizes. I would like to get an Array containing the values of any value propery. So for the above object the desired output would be:

['Kosher', 'Halal', 'Vegan']

Order doesn't really matter. I tried to do so recursively as such:

  getListOfLabels = obj => {
    const lst = []
    for (let key in obj) {
      if (obj[key].value) lst.push(obj[key].value)
      else return getListOfLabels(obj[key])
    }
    return lst
  }

but I keep getting a RangeError: Maximum call stack size exceeded error.

Any suggestions?

Upvotes: 0

Views: 1053

Answers (3)

adamz4008
adamz4008

Reputation: 650

Here's a succinct approach using reduce :-D

const getValues = options => Object.values(options)
  .reduce((acc, optionObj) => (
    optionObj.value ? [ ...acc, optionObj.value ] : [
    ...acc,
    ...Object.values(optionObj).reduce((arr, { value }) => ([ ...arr, value ]), [])
  ]), [])

Upvotes: 0

Nina Scholz
Nina Scholz

Reputation: 386680

You could take a recursive approach and check if the object contains a value key.

function getValues(object, key) {
    if (key in object) return [object[key]];
    
    return Object.values(object).reduce((r, v) => {
        if (v && typeof v === 'object') r.push(...getValues(v, key));
        return r;
    }, []);
}

var options = { religous: { kosher: { value: 'Kosher', chosen: false }, halal: { value: 'Halal', active: false } }, vegan: { value: 'Vegan', active: false } };

console.log(getValues(options, 'value'));

Upvotes: 0

Ori Drori
Ori Drori

Reputation: 192287

The for...in loop assigns the key. To get the value use obj[key]. If the key is value add to lst, if it's an object, call getListOfLabels on it, and spread the results into lst.push():

const options = {"religous":{"kosher":{"value":"Kosher","chosen":false},"halal":{"value":"Halal","active":false}},"vegan":{"value":"Vegan","active":false}}


const getListOfLabels = obj => {
  const lst = []
  
  for (let key in obj) {
    const val = obj[key] // get the value
    if (key === 'value') lst.push(val) // if the key name is "value" push to lst
    else if(typeof val === 'object') lst.push(...getListOfLabels(val)) // if type of value is object, iterate it with getListOfLabels and push the results into lst
  }
  
  return lst
}

const result = getListOfLabels(options)

console.log(result)

Upvotes: 2

Related Questions