0

How to remove an object (element) based on the property from nested obj. For example, I need to remove all objects with type: 'green' from obj tree if obj has children it will be also removed.

const obj = {
  id: '01',
  children: [
    {
      id: '02',
      type: 'green',
      children: [
        {
          id: '03',
          type: 'black',
          children: [],
        },
        {
          id: '04',
          type: 'green',
          children: [
            {
              id: '05',
              type: 'white',
              children: [],
            }
          ],
        }
      ],
    },
    {
      id: '06',
      type: 'black',
      children: [
        {
          id: '07',
          type: 'green',
          children: [],
        },
        {
          id: '08',
          type: 'white',
          children: [
            {
              id: '09',
              type: 'green',
              children: [],
            }
          ],
        }
      ],
    },
  ]
}

// expected result (if remove type: "green")

const expectedObj = {
  id: '01',
  type: 'orange',
  children: [
    {
      id: '06',
      type: 'black',
      children: [
        {
          id: '08',
          type: 'white',
          children: [],
        }
      ],
    },
  ]
}

What I am trying to do

let match = false
const removeByType = (data, type) => {
  match = data.some(d => d.type == type)
  if (match) {
    data = data.filter(d => d.type !== type)
  } else {
    data.forEach(d => {
      d.children = removeByType(d.children, type)
    })
  }
  return data
}

let data = obj.children
console.dir(removeByType(data, 'black'), { depth: null })

but { id: '03', type: 'black', children: [] } is still in the object tree

2
  • what is the logic for creating the type: 'orange' for id '01' ? Commented Nov 20, 2022 at 1:23
  • @MisterJojo there is no logic, just diff type Commented Nov 20, 2022 at 2:06

2 Answers 2

3

You were close, just missing that each instance was an array that you had to map through

const removeByType = (data, type) => {
  data = data.filter(d => d.type !== type)
  data = data.map(d => {
    d.children = removeByType(d.children, type);
    return d;
  })
  return data
}

Here's a more concise and optimized version:

const removeByType = (data, type) => data.filter(d => d.type !== type)
    .map(d => ({...d, children: removeByType(d.children, type)}));

const obj = {
  id: '01',
  children: [{
      id: '02',
      type: 'green',
      children: [{
          id: '03',
          type: 'black',
          children: [],
        },
        {
          id: '04',
          type: 'green',
          children: [{
            id: '05',
            type: 'white',
            children: [],
          }],
        }
      ],
    },
    {
      id: '06',
      type: 'black',
      children: [{
          id: '07',
          type: 'green',
          children: [],
        },
        {
          id: '08',
          type: 'white',
          children: [{
            id: '09',
            type: 'green',
            children: [],
          }],
        }
      ],
    },
  ]
}


const removeByType = (data, type) => {
  data = data.filter(d => d.type !== type)
  data = data.map(d => {
    d.children = removeByType(d.children, type);
    return d;
  })
  return data
}

console.dir(removeByType(obj.children, 'black'), {
  depth: null
})

Sign up to request clarification or add additional context in comments.

Comments

2

I've done that..

const removeByType = (data, type) =>
  {
  for (let i=data.children.length;--i>=0;)
    {
    if ( data.children[i].type===type)  data.children.splice(i,1)
    else                    removeByType (data.children[i], type)
    }
  return data // just for chaining ... ?
  }

usage:

const my_obj = 
  { id: '01',             type: 'orange', children:       // + stay
    [ { id: '02',         type: 'green',  children:          // - green
        [ { id: '03',     type: 'black',  children: [] }     // -
        , { id: '04',     type: 'green',  children:          // -
            [ { id: '05', type: 'white',  children: [] }     // -
            ] 
      } ] } 
    , { id: '06',         type: 'black',  children:       // + stay
        [ { id: '07',     type: 'green',  children: [] }     // - green
        , { id: '08',     type: 'white',  children:       // + stay
            [ { id: '09', type: 'green',  children: [] }     // - green
            ] 
  } ] } ] } 

const removeByType = (data, type) =>
  {
  for (let i=data.children.length;--i>=0;)
    {
    if ( data.children[i].type===type)  data.children.splice(i,1)
    else                    removeByType (data.children[i], type)
    }
  return data
  }

console.log( removeByType(my_obj, 'green') )
 // my_obj is now updated...
console.log( my_obj )
.as-console-wrapper {max-height: 100% !important;top: 0;}
.as-console-row::after {display: none !important;}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.