kasp3rsky
kasp3rsky

Reputation: 167

JavaScript - Edit nested objects

I have one array of nested objects. I want to edit each of them and add property "status" and value of this property can be "selected", "unselected" or "indent".

1. status: 'selected'

2. status: 'unselected'

3. status: 'indent'

all children means all nested children

Does anyone has idea how to do that?

let data = [{
    id: 1,
    name: 'level1',
    lvlScope: [1, 2, 3],
    lvl1Subs: []
  },
  {
    id: 2,
    name: 'level1',
    lvlScope: [],
    lvl1Subs: [{
        id: 1,
        name: 'level2',
        lvlScope: [],
        lvl2Subs: [{
            id: 1,
            name: 'level3',
            lvlScope: [],
            lvl3Subs: []
          },
          {
            id: 2,
            name: 'level3',
            lvlScope: [1, 2],
            lvl3Subs: []
          },
          {
            id: 3,
            name: 'level3',
            lvlScope: [1],
            lvl3Subs: [{
                id: 1,
                name: 'level4',
                lvlScope: [],
                lvl4Subs: [{
                    id: 1,
                    name: 'level5',
                    lvlScope: []
                  },
                  {
                    id: 2,
                    name: 'level5',
                    lvlScope: [1]
                  }
                ]
              },
              {
                id: 2,
                name: 'level4',
                lvlScope: [],
                lvl4Subs: []
              }
            ]
          }
        ]
      },
      {
        id: 2,
        name: 'level2',
        lvlScope: [1],
        lvl2Subs: []
      }
    ]
  },
  {
    id: 3,
    name: 'level1',
    lvlScope: [],
    lvl1Subs: [{
        id: 1,
        name: 'level2',
        lvlScope: [1, 2],
        lvl2Subs: []
      },
      {
        id: 2,
        name: 'level2',
        lvlScope: [],
        lvl2Subs: []
      },
      {
        id: 3,
        name: 'level2',
        lvlScope: [1, 2, 3],
        lvl2Subs: [{
          id: 1,
          name: 'level3',
          lvlScope: [],
          lvl3Subs: []
        }]
      },
      {
        id: 4,
        name: 'level2',
        lvlScope: [],
        lvl2Subs: []
      },
      {
        id: 5,
        name: 'level2',
        lvlScope: [1, 2],
        lvl2Subs: []
      }
    ]
  }
]

const levels = (data) => {

  data.map((lvl1) => {
    console.log('-lvl1', lvl1)
    lvl1.lvl1Subs.map((lvl2) => {
      console.log('--lvl2', lvl2)
      lvl2.lvl2Subs.map((lvl3) => {
        console.log('---lvl3', lvl3)
        lvl3.lvl3Subs.map((lvl4) => {
          console.log('----lvl4', lvl4)
          lvl4.lvl4Subs.map((lvl5) => {
            console.log('-----lvl5', lvl5)
          })
        })
      })
    })
  })
}

console.log(levels(data))

Upvotes: 1

Views: 424

Answers (2)

Nicola Scionti
Nicola Scionti

Reputation: 536

You didn't say anything about what to assign when the level has no children. Furthermore is not clear if the check should be done only to direct childs or also in the nested child. Here is a solution considering that no child means selected or unselected and considering the check only to direct childs.

const addStatus = (data, level = 1) => {
  const scope = emptyScope(data);
  let childrenScopes = [];
  for (let child of data["lvl" + level + "Subs"]
    ? data["lvl" + level + "Subs"]
    : []) {
    childrenScopes.push(emptyScope(child));
    addStatus(child, level + 1);
  }

  let status = "indent";
  let found = childrenScopes.find((c) => c === !scope);
  if (found === true || found === false) {
    found = true;
  } else {
    found = false;
  }
  if ((!found || !childrenScopes.length) && !scope) {
    status = "selected";
  }
  if ((!found || !childrenScopes.length) && scope) {
    status = "unselected";
  }

  data["status"] = status;
};

const emptyScope = (data) => {
  if (data.lvlScope.length > 0) {
    return false;
  }
  return true;
};

data.map((d) => addStatus(d, 1));

console.log(data);

Edit after information was provided in comment

const addStatus = (data, level = 1) => {
  const scope = emptyScope(data);
  let childrenScopes = childScopes(data, level, []);

  let status = "indent";
  let found = typeof childrenScopes.find((c) => c === !scope) === "boolean";

  if ((!found || !childrenScopes.length) && !scope) {
    status = "selected";
  }
  if ((!found || !childrenScopes.length) && scope) {
    status = "unselected";
  }

  data["status"] = status;

  for (let child of data["lvl" + level + "Subs"]
    ? data["lvl" + level + "Subs"]
    : []) {
    addStatus(child, level + 1);
  }
};

const childScopes = (data, level, scopes) => {
  for (let child of data["lvl" + level + "Subs"]
    ? data["lvl" + level + "Subs"]
    : []) {
    scopes.push(emptyScope(child));
    childScopes(data["lvl" + level + "Subs"], level, scopes);
  }
  return scopes;
};

const emptyScope = (data) => {
  if (data.lvlScope.length > 0) {
    return false;
  }
  return true;
};

data.map((d) => addStatus(d, 1));

console.log(data);

Upvotes: 1

abhishek sahu
abhishek sahu

Reputation: 648

you can easily solve this problem think in the way of a recursive function.

Upvotes: 0

Related Questions