Home > Back-end >  filter nested array of objects depending on children conditions
filter nested array of objects depending on children conditions

Time:05-28

there is a tree of categories. its an array of objects (in this case 1 ob ject with children property. children property is an array containing or not containing other categories objects and so on ). Each object also has a property "disabled". It can be either true or false. The starting point is that some bottommost children "disabled" are set to true. In this case all of them are set to true. The task is to find parents ids which disabled have to be set to true if all of its children disabled are set to true. In this particular case all parents ids have to be found because all bottommost children disabled are set to true. My function returns only lowest level of parents. What am I doing wrong?

let parentIdsToDisable = [];
    function findParentIdsToDisable(tree) {
      tree.forEach((category) => {
        if (category.children.length > 0) {
          if (category.children.every((child) => child.disabled === true)) {
            category.disabled = true;
            parentIdsToDisable.push(category.id);
          }
        }
        findParentIdsToDisable(category.children);
      });
  }

const categories = [
  {
    id: 69,
    name: 'Прикраси',
    key: 'prykrasy',
    description: 'Прикраси',
    disabled: false,
    mpath: '69.',
    children: [
       {
        id: 70,
        name: 'Аксесуари',
        key: 'aksesyary-dlya-prykras',
        description: 'Аксесуари для прикрас',
        disabled: true,
        mpath: '69.70.',
        children: []
      },
       {
        id: 72,
        name: 'Ювелірні вироби',
        key: 'uvelirni-vyroby',
        description: 'Ювелірні вироби',
        disabled: false,
        mpath: '69.72.',
        children: [
          {
            id: 73,
            name: 'Срібло',
            key: 'vyroby-iz-sribla',
            description: 'Ювелірні вироби із срібла',
            disabled: true,
            mpath: '69.72.73.',
            children: []
          }
        ]
      },
       {
        id: 71,
        name: 'Біжутерія',
        key: 'bizhuteriya',
        description: 'Біжутерія',
        disabled: true,
        mpath: '69.71.',
        children: []
      }
    ]
  }
]

CodePudding user response:

You need to recurse and apply the logic to each child before checking whether each child is disabled to see whether to disable the parent or not.

const categories=[{id:69,name:"Прикраси",key:"prykrasy",description:"Прикраси",disabled:!1,mpath:"69.",children:[{id:70,name:"Аксесуари",key:"aksesyary-dlya-prykras",description:"Аксесуари для прикрас",disabled:!0,mpath:"69.70.",children:[]},{id:72,name:"Ювелірні вироби",key:"uvelirni-vyroby",description:"Ювелірні вироби",disabled:!1,mpath:"69.72.",children:[{id:73,name:"Срібло",key:"vyroby-iz-sribla",description:"Ювелірні вироби із срібла",disabled:!0,mpath:"69.72.73.",children:[]}]},{id:71,name:"Біжутерія",key:"bizhuteriya",description:"Біжутерія",disabled:!0,mpath:"69.71.",children:[]}]}];

const disableObjectIfChildrenDisabled = (parent) => {
    for (const child of parent.children ?? []) {
        disableObjectIfChildrenDisabled(child);
    }
    if (parent.children?.every(child => child.disabled)) {
        parent.disabled = true;
    }
};
for (const parent of categories) {
    disableObjectIfChildrenDisabled(parent);
}
console.log(categories);

CodePudding user response:

You need to place the recursive call first, and also save the current item's id if it itself is disabled.

function findParentIdsToDisable(tree) {
  tree.forEach((category) => {
    findParentIdsToDisable(category.children);
    if (category.disabled) {
      parentIdsToDisable.push(category.id);
    }
    if (category.children.length > 0) {
      if (category.children.every((child) => child.disabled === true)) {
        category.disabled = true;
        parentIdsToDisable.push(category.id);
      }
    }
  });
}

This results in [ 70, 73, 72, 71, 69 ] for your data.

  • Related