Home > Mobile >  Copying an array of objects
Copying an array of objects

Time:11-21

Let's say we have an array of objects as below:

const example = [
  { id: "1", childIds: ["2"], parentId: "0" },
  { id: "2", childIds: ["3", "4"], parentId: "1" },
  { id: "3", childIds: [], parentId: "2" },
  { id: "4", childIds: ["5", "6"], parentId: "2" },
  { id: "5", childIds: [], parentId: "4" },
  { id: "6", childIds: [], parentId: "4" },
];

Problem: Copy this object, by generating new IDs.

IDs can be different ofc. Assume that we're using a 3rd party ID generator function to handle it. But the new IDs should match to keep the child-parent relation.

So, how would your JS function look like to solve this problem?

Expected result:

const copied = [
  { id: "10", childIds: ["20"], parentId: "0" },
  { id: "20", childIds: ["30", "40"], parentId: "10" },
  { id: "30", childIds: [], parentId: "20" },
  { id: "40", childIds: ["50", "60"], parentId: "20" },
  { id: "50", childIds: [], parentId: "40" },
  { id: "60", childIds: [], parentId: "40" },
];

This is what I tried (getting error: TypeError: Cannot assign to read only property 'parentId' of object '#')

      const copied = [];

      example.forEach((child) => {
        const newId = generateId();

        // check if this child is parent of other elements, then update parentIds
        const childrenOfThisChild = example.filter(
          (el) => el.parentId === child.id
        );
        if (childrenOfThisNode.length) {
          childrenOfThisNode.forEach(
            (child) => (child = { ...child, parentId: newId })
          );
        }

        // check if this child is child of other elements, then update childIds
        example.forEach((el) => {
          const index = el.childIds.indexOf(child.id);
          if (index !== -1) {
            el.childIds[index] = newId;
          }
        });

        // add the currently iterated object to new copied array
        copied.push({ ...child, id: newId });
      });

CodePudding user response:

You loop over the array once, changing all the ids of your objects (and saving what id changed to what in a lookup object). Then you loop again and change all teh childIds and parentIds based on your lookup object.

const example = [
  { id: "1", childIds: ["2"], parentId: null },
  { id: "2", childIds: ["3", "4"], parentId: "1" },
  { id: "3", childIds: [], parentId: "2" },
  { id: "4", childIds: ["5", "6"], parentId: "2" },
  { id: "5", childIds: [], parentId: "4" },
  { id: "6", childIds: [], parentId: "4" },
];

const newIds = [10, 20, 30, 40, 50, 60, 70]

//I'm just gonna make the assumption, that you are getting an array of unique IDs from the 3rd party
function replaceIds (array, idsArray) {
  const lookup = {};
  
  const retArr = array.map(obj => {return { ...obj }})
  
  retArr.forEach((obj, index) => {
    lookup[obj.id] = idsArray[index]
    obj.id = idsArray[index]
  })
  
  retArr.forEach(obj => {
    obj.parentId = lookup[obj.parentId] || null;
    obj.childIds = obj.childIds.map(id => lookup[id])
  })
  return retArr
}

console.log(replaceIds(example, newIds))

If you have trouble with the requirement for a newIDs array. you can easily create one with some code like this:

const IdArray = newArray(example.length)
IdArray.map(x => generateId())

CodePudding user response:

You can try something like this:

function generateId() {
  return Math.floor(Math.random() * 100)   "";
}

const example = [
  { id: "1", childIds: ["2"], parentId: "0" },
  { id: "2", childIds: ["3", "4"], parentId: "1" },
  { id: "3", childIds: [], parentId: "2" },
  { id: "4", childIds: ["5", "6"], parentId: "2" },
  { id: "5", childIds: [], parentId: "4" },
  { id: "6", childIds: [], parentId: "4" },
];

var copied = [];
example.forEach((ex, i) => {
    const parentId = i === 0 ? "0" : copied[parseInt(i / 2)].id;
    copied.push({
        id: generateId(),
        childIds: Array.from({ length: ex.childIds.length }).map(() => generateId()),
        parentId
    });
});
  • Related