Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

delete an array element inside array of array

Hi I am trying to delete an element which is inside array of array. my schema is :

var mySchema = Schema({ 
  primaryField:String,
  list1: [{
    item1: String,
    item2:String
  }],
  list2 : [{
  item3:String,
    item4 : [String]//item4 is string values available in item1
  }]
});

for ex:

{
  "primaryField": "abc",
  "list1": [{
    "item1": "aa",
    "item2": "mystring"
  },{
    "item1": "bb",
    "item2": "sampStr"
  }],
  "list2": [{
    "item3": "stringitem",
    "item4": ["aa", "bb"]
  },{
    "item3": "sample",
    "item4": ["bb"]
  },{
    "item3": "samplestring",
    "item4": ["aa"]
  }]
}

I have to delete the "aa" items from list1 and the occurence of "aa" in list2.item4 and if only "aa" is present in item4 then i have to delete the entire object entry.

my output should be:

{
  "primaryField": "abc",
  "list1": [{
    "item1": "bb",
    "item2": "sampStr"
  }],
  list2:[{
    "item3": "stringitem",
    "item4": ["bb"]
  },{
    "item3": "sample",
    "item4": ["bb"]
  }]
}

could anyone help me to achieve this using node.js and mongoose. Schema cannot be modified.

like image 946
Nizam Avatar asked Mar 04 '26 18:03

Nizam


1 Answers

This produce the expected output. It should be generic enough, and I'm not sure if it will work with your code, but given what's specified in the question, I think it should be fine.

function removeAllItems(obj, value) {
  var deleted;

  if (!obj) {
    return false;
  }

  if (obj === value) {
    deleted = true;
  } else if (Array.isArray(obj)) {
    for (var i = 0, len = obj.length; i < len; ++i) {
      if (removeAllItems(obj[i], value)) {
        obj.splice(i--, 1);

        if (!obj.length) {
          deleted = true;
        }
      }
    }
  } else if (typeof obj === 'object') {
    for (var keys = Object.keys(obj), key, i = 0, len = keys.length; i < len; ++i) {
      if (removeAllItems(obj[keys[i]], value)) {
        delete obj[keys[i]];

        deleted = true;
      }
    }
  }

  return deleted;
}

Tested with :

var test = {
  "primaryField": "abc",
  "list1": [{
    "item1": "aa",
    "item2": "mystring"
  },{
    "item1": "bb",
    "item2": "sampStr"
  }],
  "list2": [{
    "item3": "stringitem",
    "item4": ["aa", "bb"]
  },{
    "item3": "sample",
    "item4": ["bb"]
  },{
    "item3": "samplestring",
    "item4": ["aa"]
  }]
};

var valueToRemove = 'aa';

removeAllItems(test, valueToRemove);
console.log('Removing all', valueToRemove, JSON.stringify(test, null, 2));

Gives the result

Removing all aa {
  "primaryField": "abc",
  "list1": [
    {
      "item1": "bb",
      "item2": "sampStr"
    }
  ],
  "list2": [
    {
      "item3": "stringitem",
      "item4": [
        "bb"
      ]
    },
    {
      "item3": "sample",
      "item4": [
        "bb"
      ]
    }
  ]
}

Here is an update that take into account cyclical references, and returns true if any value was removed, or false otherwise.

function removeAllItems(obj, value) {
  var stack = [];
  var found = false;

  function _next(obj) {
    var deleted;

    if (!obj) {
      return false;
    } else if (stack.indexOf(obj) >= 0) {
      return false;   // cyclical reference found
    }

    stack.push(obj);

    if (obj === value) {
      found = deleted = true;
    } else if (Array.isArray(obj)) {
      for (var i = 0, len = obj.length; i < len; ++i) {
        if (_next(obj[i])) {
          obj.splice(i--, 1);

          if (!obj.length) {
            deleted = true;
          }
        }
      }
    } else if (typeof obj === 'object') {
      for (var keys = Object.keys(obj), key, i = 0, len = keys.length; i < len; ++i) {
        if (_next(obj[keys[i]])) {
          delete obj[keys[i]];

          deleted = true;
        }
      }
    }

    stack.pop();

    return deleted;
  }

  return _next(obj), found;
}
like image 196
Yanick Rochon Avatar answered Mar 06 '26 07:03

Yanick Rochon



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!