cup_of
cup_of

Reputation: 6687

Move item anywhere in a nested array

I've managed to copy the intended object into the intended location (my code is below), but how do I move it? So it will not exist in the original location any more.

So in my example, I want to take the object with id of 14 (very bottom of the object) and move it into the children of the object with id of 3 (towards the top).

I know I need to modify this line: item.children.push(itemToMove) in my moveItem function, but some reason I can't think of it.

Also sorry about the very big/nested object, I wanted to make sure to cover a deeply nested object.

const myObj = [
  {
    id: 1,
    name: '1',
    children: [
      {
        id: 2,
        name: '2',
        children: [
          {
            id: 3,
            name: '3',
            children: []
          }
        ]
      },
      {
        id: 4,
        name: '4',
        children: [
          {
            id: 5,
            name: '5',
            children: [
              {
                id: 6,
                name: '6',
                children: [
                  {
                    id: 7,
                    name: '7',
                    children: []
                  }
                ]
              }
            ]
          }
        ]
      },
    ]
  },
    {
    id: 8,
    name: '8',
    children: [
      {
        id: 9,
        name: '9',
        children: [
          {
            id: 10,
            name: '10',
            children: []
          }
        ]
      },
      {
        id: 11,
        name: '11',
        children: [
          {
            id: 12,
            name: '12',
            children: [
              {
                id: 13,
                name: '13',
                children: [
                  {
                    id: 14,
                    name: '14',
                    children: []
                  }
                ]
              }
            ]
          }
        ]
      },
    ]
  }
]

let itemToMove = {
  id: 14,
  name: '14',
  children: []
}

// move item, return updated obj
function moveItem(itemToMove, obj, parentId) {

  for (let i=0;i<obj.length;i++) {
    const value = obj[i];
    const item = search(obj[i], parentId);
    if (item) {
      item.children.push(itemToMove); // pushed into children, but need to move not duplicate in
      break;
    }
  }

  function search(obj, id) {
    if (obj.id === id) {
      return obj;
    }

    for (let i=0;i<obj.children.length;i++) {
      const possibleResult = search(obj.children[i], id);
        if (possibleResult) {
          return possibleResult;
        }
    }
  }

  return obj;
};

console.log(moveItem(itemToMove, myObj, 3))

Upvotes: 0

Views: 677

Answers (1)

Andrew MacNaughton
Andrew MacNaughton

Reputation: 813

I would probably do something like this, taking into account that if the insert fails, you should have some kind of way to re-instate the data. I also used ES6 which is different to your code, but it gives you some kind of idea.

let parent
function removeItem (obj, itemToFind) {
	// Loop the object
  obj.find((e, index) => {
		// If the id's match remove from the parent if it exists otherwise from the object as its at root level
    if (e.id === itemToFind.id) {
      if (parent) {
        parent.children.splice(index, 1)
      } else {
        obj.splice(index, 1)
      }
			// break the loop once returned true. Change find to forEach to remove all instances with id if allowing multiples
      return true
    }
		// recurse
    else if (e.children && e.children.length > 0) {
      parent = e
      return removeItem(e.children, itemToFind)
    }
  })
}
// move item, return updated obj
function moveItem (itemToMove, obj, parentId) {
  for (let i = 0; i < obj.length; i++) {
    const value = obj[i]
    const item = search(obj[i], parentId)
    if (item) {
      item.children.push(itemToMove) // pushed into children, but need to move not duplicate in
      break
    }
  }

  function search (obj, id) {
    if (obj.id === id) {
      return obj
    }

    for (let i = 0; i < obj.children.length; i++) {
      const possibleResult = search(obj.children[i], id)
      if (possibleResult) {
        return possibleResult
      }
    }
  }

  return obj
};
removeItem(myObj, itemToMove)
moveItem(itemToMove, myObj, 3)

Upvotes: 1

Related Questions