How would I find all values by specific key in a deep nested object?
For example, if I have an object like this:
const myObj = {
  id: 1,
  children: [
    {
      id: 2,
      children: [
        {
          id: 3
        }
      ]
    },
    {
      id: 4,
      children: [
        {
          id: 5,
          children: [
            {
              id: 6,
              children: [
                {
                  id: 7,
                }
              ]
            }
          ]
        }
      ]
    },
  ]
}
How would I get an array of all values throughout all nests of this obj by the key of id.
Note: children is a consistent name, and id's won't exist outside of a children object.
So from the obj, I would like to produce an array like this:
const idArray = [1, 2, 3, 4, 5, 6, 7]
                This is a bit late but for anyone else finding this, here is a clean, generic recursive function:
function findAllByKey(obj, keyToFind) {
  return Object.entries(obj)
    .reduce((acc, [key, value]) => (key === keyToFind)
      ? acc.concat(value)
      : (typeof value === 'object')
      ? acc.concat(findAllByKey(value, keyToFind))
      : acc
    , [])
}
// USAGE
findAllByKey(myObj, 'id')
                        let str = JSON.stringify(myObj);
let array = str.match(/\d+/g).map(v => v * 1);
console.log(array); // [1, 2, 3, 4, 5, 6, 7]
                        You could make a recursive function like this:
idArray = []
function func(obj) {
  idArray.push(obj.id)
  if (!obj.children) {
    return
  }
  obj.children.forEach(child => func(child))
}
Snippet for your sample:
const myObj = {
  id: 1,
  children: [{
      id: 2,
      children: [{
        id: 3
      }]
    },
    {
      id: 4,
      children: [{
        id: 5,
        children: [{
          id: 6,
          children: [{
            id: 7,
          }]
        }]
      }]
    },
  ]
}
idArray = []
function func(obj) {
  idArray.push(obj.id)
  if (!obj.children) {
    return
  }
  obj.children.forEach(child => func(child))
}
func(myObj)
console.log(idArray)
I found steve's answer to be most suited for my needs in extrapolating this out and creating a general recursive function. That said, I encountered issues when dealing with nulls and undefined values, so I extended the condition to accommodate for this. This approach uses:
Array.reduce() - It uses an accumulator function which appends the value's onto the result array. It also splits each object into it's key:value pair which allows you to take the following steps:
Hope it helps!
const myObj = {
  id: 1,
  children: [{
      id: 2,
      children: [{
        id: 3
      }]
    },
    {
      id: 4,
      children: [{
        id: 5,
        children: [{
          id: 6,
          children: [{
            id: 7,
          }]
        }]
      }]
    },
  ]
}
function findAllByKey(obj, keyToFind) {
  return Object.entries(obj)
    .reduce((acc, [key, value]) => (key === keyToFind)
      ? acc.concat(value)
      : (typeof value === 'object' && value)
      ? acc.concat(findAllByKey(value, keyToFind))
      : acc
    , []) || [];
}
const ids = findAllByKey(myObj, 'id');
console.log(ids)
You can make a generic recursive function that works with any property and any object.
This uses Object.entries(), Object.keys(), Array.reduce(), Array.isArray(), Array.map() and Array.flat().
The stopping condition is when the object passed in is empty:
const myObj = {
  id: 1,
  anyProp: [{
    id: 2,
    thing: { a: 1, id: 10 },
    children: [{ id: 3 }]
  }, {
    id: 4,
    children: [{
      id: 5,
      children: [{
        id: 6,
        children: [{ id: 7 }]
      }]
    }]
  }]
};
const getValues = prop => obj => {
  if (!Object.keys(obj).length) { return []; }
  return Object.entries(obj).reduce((acc, [key, val]) => {
    if (key === prop) {
      acc.push(val);
    } else {
      acc.push(Array.isArray(val) ? val.map(getIds).flat() : getIds(val));
    }
    return acc.flat();
  }, []);
}
const getIds = getValues('id');
console.log(getIds(myObj));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With