简体   繁体   中英

condensing the array object recursively in javascript

I have an array of objects in the below format:

{
  "country": "India",
  "children": [
    {
      "name": "Karnataka",
      "type": "State",
      "children": [
        {
          "name": "",
          "type": "city"
        },
        {
          "name": "Bangalore",
          "type": "city"
        },
        {
          "name": "Mangalore",
          "type": "city"
        }
      ]
    },
    {
      "name": "Kerala",
      "type": "State",
      "children": [
        {
          "name": "",
          "type": "city"
        }
      ]
    },
    {
      "name": "Maharashtra",
      "type": "State",
      "children": [
        {
          "name": "Mumbai",
          "type": "city"
        },
        {
          "name": "Pune",
          "type": "city"
        }
      ]
    }
  ]
}

Every object has a children element which contains the details of the element. I need to recursively iterate through the json object and remove all the nodes whose name is empty string up till the root. For the above json format, the output should be like below:

{
  "country": "India",
  "children": [
    {
      "name": "Karnataka",
      "type": "State",
      "children": [
        {
          "name": "Bangalore",
          "type": "city"
        },
        {
          "name": "Mangalore",
          "type": "city"
        }
      ]
    },
    {
      "name": "Kerala",
      "type": "State",
      "children": [
      ]
    },
    {
      "name": "Maharastra",
      "type": "State",
      "children": [
        {
          "name": "Mumbai",
          "type": "city"
        },
        {
          "name": "Pune",
          "type": "city"
        }
      ]
    }
  ]
}

How to do this in javascript recursively using Underscorejs.

This is a recursive solution with Array#filter() .

 function filterName(a) { if (a.name) { if (Array.isArray(a.children)) { a.children = a.children.filter(filterName); } return true; } } var object = { "country": "India", "children": [{ "name": "Karnataka", "type": "State", "children": [{ "name": "", "type": "city" }, { "name": "Bangalore", "type": "city" }, { "name": "Mangalore", "type": "city" }] }, { "name": "Kerala", "type": "State", "children": [{ "name": "", "type": "city" }] }, { "name": "Maharashtra", "type": "State", "children": [{ "name": "Mumbai", "type": "city" }, { "name": "Pune", "type": "city" }] }] }; object.children.forEach(filterName); document.write("<pre>" + JSON.stringify(object, 0, 4) + "</pre>"); 

Try this:

function condense(arr) {

  arr.children = arr.children.map(function(c) {
    c.children = c.children.filter(function(c1) {
      return c1.name;
    });
    return c;
  });

  return arr;
}

I iterate through the children (with map ), then filter the children array with filter . Only the children with a name not null or empty will be kept.

Here is a jsfiddle .

Not au fait with underscore.js. You can do this with ES5 reduceRight and delete members that you don't want, it should be more efficient than other approaches. The following uses recursion (which isn't as efficient as serial processing but is likely less code), so you can nest the objects as deep as you like:

 function removeEmpty(obj) { obj.children.reduceRight(function (acc, child, i) { if (!child.name) { obj.children.splice(i, 1); } else if (child.children) { removeEmpty(child); } return null; }, null); return obj; } // Test var data = { "country": "India", "children": [ { "name": "Karnataka", "type": "State", "children": [ { "name": "", "type": "city" }, { "name": "Bangalore", "type": "city" }, { "name": "Mangalore", "type": "city" } ] }, { "name": "Kerala", "type": "State", "children": [ { "name": "", "type": "city" } ] }, { "name": "Maharashtra", "type": "State", "children": [ { "name": "Mumbai", "type": "city" }, { "name": "Pune", "type": "city" } ] } ] } document.write('Original:<br>' + JSON.stringify(data) + '<br><br>' + 'Modified:<br>' + JSON.stringify(removeEmpty(data))); 

This is very specific to your example.

Link to fiddle

 var obj = { "country": "India", "children": [{ "name": "Karnataka", "type": "State", "children": [{ "name": "", "type": "city" }, { "name": "Bangalore", "type": "city" }, { "name": "Mangalore", "type": "city" }] }, { "name": "Kerala", "type": "State", "children": [{ "name": "", "type": "city" }] }, { "name": "Maharashtra", "type": "State", "children": [{ "name": "Mumbai", "type": "city" }, { "name": "Pune", "type": "city" }] }] }; //Before document.write("BEFORE: "+JSON.stringify(obj)); //After document.write("AFTER: "+JSON.stringify(checkJSON(obj))); function checkJSON(obj) { $.each(obj.children, function(index, value) { if ($.isArray(value.children)) { $.each(value.children, function(index, value) { if (value.name == '') { delete value.name; } }); } }); return obj; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> 

Probably not the shortest way, but it works:

obj.children = _.each(obj.children, filter);

function filter(child, index, arr) {
  if (child && child.name === '') {
    // remove the ones without name
    arr.splice(index, 1);

  } else if (_.has(child, 'children')) {
    // remove nested children
    child.children = _.each(child.children, filter);

    // check for empty children array and remove it (if needed)
    /*
    if (child.children.length === 0) {
      delete child['children'];
    }
    */
  }

  return child;
}

Fiddle: https://jsfiddle.net/gnmosu5p/2/

I know a recursive approach is asked but i can't help myself from giving a single liner here.

var newData = JSON.parse(JSON.stringify(data).replace(/{"name":"".+?},?/g, ""));

where data is the initially given object to be restructured.

It's somewhat slower than array functions but one advantage of this method is preserving the original data object as it is while all array methods will override the original data object unless you clone it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM