0

I have an array of nested objects. These objects take one of two forms:

// type a
{
    value: 'some value'
}

or

// type b
{
    array: [
        object of type a or b,
        object of type a or b,
        ...
    ]
}

So, the base array can be nested infinitely. Given a series of indices (I've been calling it a 'tree'), how can I remove a single item at any depth?

A sample of what I have so far:

const baseArray = [
    { value: 'some value' },
    { array: [
            { value: 'some value' },
            { array: [
                    { value: 'some value' },
                    { value: 'some value' },
                ],
            },
            { value: 'some value' },
            { array: [
                    { value: 'some value' },
                    { array: [
                            { value: 'delete me' },
                            { value: 'some value' },
                        ]
                    },
                ],
            },
        ],
    }
]

const tree = [1, 3, 1, 0]

function deleteNested(tree, inputArray) {
    const index = tree.shift();
    console.log(inputArray, index);
    const child = inputArray[index].array;
    if (tree.length > 0) {
        console.log(child)
        return deleteNested(tree, child);
    }
    return [
        ...inputArray.slice(0, index),
        ...inputArray.slice(index + 1)
    ]
}
const originalArray = baseArray.slice(0);
console.log(deleteNested(tree, baseArray), originalArray);

I want to delete the marked object given it's 'tree' location: [1, 3, 1, 0]:

  • first, look in the 1 (index of 1, not 0) value of the initial array,
  • then the 3 value,
  • then look at the 1 value,
  • then finally remove the 0 value.

What I have above isn't working, but has gotten me started.

The function needs to be recursive to work at any depth. It should ideally not use splice() to avoid modifying the array passed into it -- rather, it should return a new one.

1
  • I guess instead of recursion a while loop would be more appropriate since you already know the number of iterations in advance. Commented Oct 3, 2016 at 7:44

3 Answers 3

1

As i said in the comments if you know the number of iterations in advance you shouldn't use a recursive approach. A while loop is ideal such as;

function delNestedItem(a,dm){
  var i = 0;
  while (i < dm.length-1) a = a[dm[i++]].array;
  a.splice(dm[i],1);
}

var data = [
    { value: 'some value' },
    { array: [
            { value: 'some value' },
            { array: [
                    { value: 'some value' },
                    { value: 'some value' },
                ],
            },
            { value: 'some value' },
            { array: [
                    { value: 'some value' },
                    { array: [
                            { value: 'delete me' },
                            { value: 'some value' },
                        ]
                    },
                ],
            },
        ],
    }
          ],

delMark = [1, 3, 1, 0];
delNestedItem(data,delMark);
console.log(JSON.stringify(data,null,2));

Sign up to request clarification or add additional context in comments.

Comments

0

Here's how you can do it in 1 reduce:

const baseArray = [{
  value: 'some value'
}, {
  array: [{
    value: 'some value'
  }, {
    array: [{
      value: 'some value'
    }, {
      value: 'some value'
    }, ],
  }, {
    value: 'some value'
  }, {
    array: [{
      value: 'some value'
    }, {
      array: [{
        value: 'delete me'
      }, {
        value: 'some value'
      }, ]
    }, ],
  }, ],
}];

const tree = [1, 3, 1, 0];


var deleted = tree.reduce(function(pos, pathIndex, index, arr) {
  if (index + 1 < arr.length) {
    return pos.array
      ? pos.array[pathIndex]
      : pos[pathIndex];
  } else {
    pos.array = pos.array
            .slice(0, pathIndex)
            .concat(pos.array.slice(pathIndex + 1));
    return pos;
  }

}, baseArray);
            
            console.log(baseArray);
            

Comments

0

You could generate a new array out of the given array only with the undeleted parts.

function ff(array, tree) {
    function iter(array, level) {
        var r = [];
        array.forEach(function (a, i) {
            if (tree[level] !== i) {
                return r.push(a);
            }
            if (level + 1 !== tree.length && a.array) {
                r.push({ array: iter(a.array, level + 1) });
            }
        });
        return r;
    }
    return iter(array, 0);
}

var baseArray = [{ value: 'some value' }, { array: [{ value: 'some value' }, { array: [{ value: 'some value' }, { value: 'some value' }, ], }, { value: 'some value' }, { array: [{ value: 'some value' }, { array: [{ value: 'delete me' }, { value: 'some value' }, ] }, ], }, ], }],
    tree = [1, 3, 1, 0],
    copy = ff(baseArray, tree);

console.log(copy);
console.log(baseArray);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.