skip to Main Content

I want to set the active element to false in all of the objects. This is my object:

const obj = 
  { name: 'obj1'
  , ative: true
  , children: 
    [ { name: 'obj2'
      , ative: true
      , children: 
        [ { name: 'Obj23'
          , ative: true
          , children: [...] 
      } ] } 
    , { name: 'obj3'
      , children: 
        [ { name: 'Obj32'
          , ative: true
          , children: [...] 
      } ] } 
    , ...
    } 

what I have to is, for the main object obj1 and all of the childrens, and sub childres.
I want to set the active to false.
The point is, I don’t know how many childrens there can be under each child. I would have to create some type of loop with a map or something of the kind.
I will need to stop looping when the children is equal to 0 (no length)

3

Answers


  1. There are two main approaches that can be used

    1. Iterative approach
    2. Recursive approach

    In most cases, the iterative approach is better in both memory and speed since the recursive approach requires O(n) extra memory for each invocation in the call stack.

    In the iterative approach map, and forEach array methods will be useless, since we don’t know the length and when to stop, even if manage to use them it will require us to mutate the traversed array which leads to side-effects. Instead, we are going to use a simple while loop.

    Algorithm:

    • Create a stack array and put the input object in it
    • While stack is not empty
      • Let current be the popped element from the stack
      • Set current’s active to false
      • Add current’s children into stack to traverse its children
    • Return item (optional, since we are mutating the input object)

    Implementation:

    First, let’s create a type for the input data structure:

    type Item = {
      name: string;
      active?: boolean;
      children: Item[];
    };
    

    Now, the function itself:

    const setActive = (data: Item): Item => {
      const stack = [data];
    
      while (stack.length) {
        const current = stack.pop();
    
        if (!current) continue;
    
        current.active = false;
    
        stack.push(...current.children);
      }
    
      return data;
    };
    

    playground

    Login or Signup to reply.
  2. You can also use JSON.parse with reviver function to do this:

    JSON.parse(JSON.stringify(obj), (key, value ) => key === 'ative' ? false : value );
    
    const obj = {
        name: 'obj1',
        ative: true,
        children: [{
            name: 'obj2',
            ative: true,
            children: [{
                name: 'Obj23',
                ative: true,
                children: []
            }]
        },
        {
            name: 'obj3',
            children: [{
                name: 'Obj32',
                ative: true,
                children: []
            }]
        }]
    }
    
    const result = JSON.parse(JSON.stringify(obj), (key, value) => key === 'ative' ? false : value);
    
    console.log(result);
    Login or Signup to reply.
  3. I don’t disagree with wonderflame that a stack-based approach is better if you don’t know how large your tree will grow, but if you know you will only ever go a few levels deep then the optimization might not be needed, and a recursive approach is simpler.

    function deactiveRecursive(obj) {
    
      return {
        ...obj,
        active: false,
        children: obj.children.map(child => deactivateRecursive(child));
      };
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search