5

I have a familytree looking like this:

{

    "children": [{
        "name": "bob",
        "children": [{
            "name": "sam",
            "children": [{
                "name": "mike",
                "children": [{
                    "name": "elias",
                    "children": []
                }, {
                    "name": "rodriguez",
                    "children": []
                }]
            }]
        }]
    }]
}

The main "children" is an array containing nested child-arrays. How can I remove an object from an array like this? Lets say I want to remove the object with the name "sam", that should leave me with the following:

{
    "children": [{
        "name": "bob",
        "children": []
    }]
}

Its the nesting that trips me up and i do not understand how to start.

Any help or directions to a tutorial that deals with similar issues are appreciated.

eggman
  • 111
  • 1
  • 2
  • 10
  • Assuming there are many sams, do you want to remove all of them? – georg Mar 25 '16 at 22:05
  • Based on the wording of his question, it's ambiguous - but I'd say your solution assumed the best possible interpretation. – aaaaaa Mar 25 '16 at 22:08

4 Answers4

11

Recursion is a good tool to work with trees.

var tree = {

    "children": [{
        "name": "bob",
        "children": [{
            "name": "sam",
            "children": [{
                "name": "mike",
                "children": [{
                    "name": "elias",
                    "children": []
                }, {
                    "name": "rodriguez",
                    "children": []
                }]
            }]
        }]
    }]
}

function removeFromTree(parent, childNameToRemove){
  parent.children = parent.children
      .filter(function(child){ return child.name !== childNameToRemove})
      .map(function(child){ return removeFromTree(child, childNameToRemove)});
  return parent;
}
tree = removeFromTree(tree, 'elias')         
console.log(tree);
document.write(JSON.stringify(tree));

This tutorial looks interesting (section "Binary Trees" and "Graphs"). I think it could help to implement your requirements: https://www.syncano.io/blog/data-structures-in-javascript/

Meiko Rachimow
  • 4,664
  • 2
  • 25
  • 43
4

This is a proposal which iterates over the objects and uses backtracking for deleting the wanted node with the given name.

This solution keeps the original object and uses short circuit to prevent more than necessaray iterations.

It uses recusion as well.

function deleteFromTree(o, name) {
    function getNode(a, i) {
        if (a.name === name) {
            index = i;
            return true;
        }
        if (Array.isArray(a.children) && a.children.some(getNode)) {
            if (~index) {
                a.children.splice(index, 1);
                index = -1;
            }
            return true;
        }
    }

    var index = -1;
    [o].some(getNode);
}

var tree = { "children": [{ "name": "bob", "children": [{ "name": "sam", "children": [{ "name": "mike", "children": [{ "name": "elias", "children": [] }, { "name": "rodriguez", "children": [] }] }] }] }] };

deleteFromTree(tree, 'sam');
document.write('<pre>' + JSON.stringify(tree, 0, 4) + '</pre>');
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
1

The main "children" is an array containing nested child-arrays. How can I remove an object from an array like this? Lets say I want to remove the object with the name "sam", that should leave me with the following:

{
    "children": [{
        "name": "bob",
        "children": []
    }]
}

You can utilize JSON.stringify() replacer parameter to remove properties from returned JSON string

replacer Optional
A function that alters the behavior of the stringification process, or an array of String and Number objects that serve as a whitelist for selecting the properties of the value object to be included in the JSON string. If this value is null or not provided, all properties of the object are included in the resulting JSON string.

The replacer parameter

The replacer parameter can be either a function or an array. As a function, it takes two parameters, the key and the value being stringified. The object in which the key was found is provided as the replacer's this parameter. Initially it gets called with an empty key representing the object being stringified, and it then gets called for each property on the object or array being stringified. It should return the value that should be added to the JSON string, as follows:

  • If you return a Number, the string corresponding to that number is used as the value for the property when added to the JSON string.

  • If you return a String, that string is used as the property's value when adding it to the JSON string.

  • If you return a Boolean,"true" or "false" is used as the property's value, as appropriate, when adding it to the JSON string.

  • If you return any other object, the object is recursively stringified into the JSON string, calling the replacer function on each property, unless the object is a function, in which case nothing is added to the JSON string.

  • If you return undefined, the property is not included in the output JSON string.

    Note: You cannot use the replacer function to remove values from an array. If you return undefined or a function then null is used instead.


var prop = "name";
var value = "sam";
var res = JSON.stringify(data, function re(a, obj) {;
     return obj[prop] === value ? null : obj
  }, 2);

console.log(res, JSON.parse(res));

var data = {
  "children": [{
    "name": "bob",
    "children": [{
      "name": "sam",
      "children": [{
        "name": "mike",
        "children": [{
          "name": "elias",
          "children": []
        }, {
          "name": "rodriguez",
          "children": []
        }]
      }]
    }]
  }]
};

var prop = "name";
var value = "sam";
var res = JSON.stringify(data, function re(a, obj) {;
     return obj[prop] === value ? null : obj
  }, 2);

console.log(res, JSON.parse(res));

document.querySelector("pre").textContent = res;
<pre>
</pre>
guest271314
  • 1
  • 15
  • 104
  • 177
  • i do not see anything (ie11) – Nina Scholz Mar 25 '16 at 23:00
  • @NinaScholz Interesting. Have not tried ie browser in some time. Any errors logged at `console` ? Tried at firefox , chrome / chromium browser ? What is logged at `console.log(b, b[curr[prop]])` within `for` loop ? – guest271314 Mar 25 '16 at 23:01
  • `var curr = Object.keys(b);` *Object.keys: Das Argument ist kein Objekt* translates to *'argument is no object'*. – Nina Scholz Mar 25 '16 at 23:05
  • Tried adjusting condition to `if (b && typeof b === "object")` ? What is `b` at error ? – guest271314 Mar 25 '16 at 23:08
  • @NinaScholz Well, this makes the process simpler for us, yes ? See updated post – guest271314 Mar 25 '16 at 23:20
  • @NinaScholz If `b` is `"bob"` at ie11, what does `return b === n ? null : n` produce ? – guest271314 Mar 25 '16 at 23:31
  • @NinaScholz See http://www.ecma-international.org/ecma-262/5.1/#sec-15.12.3 at 3. "If `ReplacerFunction` is not **undefined**, then" – guest271314 Mar 25 '16 at 23:36
  • @NinaScholz Curious about ie11 implementation of specification; what is result of `return b === n || b["name"] === n ? null : b` ? – guest271314 Mar 25 '16 at 23:54
  • 1
    sorry, had to sleep. but now it works perfectly. btw tricky idea to use a build in recursive iterator. – Nina Scholz Mar 26 '16 at 08:20
  • @NinaScholz _"sorry, had to sleep."_ Impossible with so much to discover ! _"but now it works perfectly."_ Was wondering if ie implementation was different. – guest271314 Mar 26 '16 at 08:25
  • @NinaScholz Could be entirely incorrect, though when trying destructuring had the sense the process was somewhat similar to `JSON.stringify` `replacer`; still exploring option of passing string to `replacer`. – guest271314 Mar 26 '16 at 08:45
-1

You can use JSON.stringify(), JSON.parse(), String.prototype.match() with RegExp /\{"name":"sam".*(?=\]\}\]\})/ to match property having property "name" with value "sam" remove remainder of string until ]}]} is portion of string with String.prototype.replace()

var res = JSON.parse(
  JSON.stringify(data)
  .replace(JSON.stringify(data).match(/\{"name":"sam".*(?=\]\}\]\})/)[0]
  , ""
  , ["children"])
);

var data = {

  "children": [{
    "name": "bob",
    "children": [{
      "name": "sam",
      "children": [{
        "name": "mike",
        "children": [{
          "name": "elias",
          "children": []
        }, {
          "name": "rodriguez",
          "children": []
        }]
      }]
    }]
  }]
}

var res = JSON.parse(
  JSON.stringify(data)
  .replace(JSON.stringify(data).match(/\{"name":"sam".*(?=\]\}\]\})/)[0]
  , ""
  , ["children"])
);

console.log(data)

document.querySelector("pre").textContent = JSON.stringify(res, null, 2);
<pre>
</pre>
guest271314
  • 1
  • 15
  • 104
  • 177