简体   繁体   中英

How to completely remove an empty array in javascript?

I have searched and searched and cannot find an answer to this, so please accept my apologies if I am being foolish.

I am building an application in node.js that uses JSON files as project configs. I am using the 'fs' module to read the JSON file, which I then parse into a Javascript object. I then amend details within the object before using JSON.stringify to write the data back to the file.

My problem is that I need to delete an array, not just empty it, in order to show the data correctly on my interface:

"floors": [
    {
        "floorName": "Grd Floor",
        "floorNotes": "",
        "floorPlan": "Buckley_Grd.jpg",
        "floorWidth": "57.392",
        "floorHeight": "20.776",
        "runs": [
            [],  *<----I cannot delete these*
            []   *<----only empty them*
            [
                {
                    "xCoOrd": "37.88235294117647",
                    "yCoOrd": "59.307359307359306",
                    "drawingType": "node"
                },
                {
                    "xCoOrd": "37.88235294117647",
                    "yCoOrd": "59.307359307359306",
                    "drawingType": "node"
                },
                {
                    "xCoOrd": "48.549019607843135",
                    "yCoOrd": "50",
                    "drawingType": "node"
                }
            ]   *<----I don't want to delete the elements in this array*
        ]
    }

I have tried:

.splice(0);
.filter(Boolean);
delete

Everywhere I have looked people seem surprised that one would want to delete an unused array from memory, which is what I beleive I am trying to do. Perhaps there is a way to stringify the object that ignores these empty arrays? Or perhaps I am doing this completely the wrong way?

Many thanks in advance for any advice offered.

EDIT: I should have made clearer that I don't necessarily want to delete all of the elemnets in the array so redeclaring floors.runs =[] unfortunately will not help me.

I have tried:

delete floors[floorID].runs[runID];

This replaces the array with null which gets written to the file and ruins my reading of the JSON.

Did you try over-writing the 'runs' property of each object? If you said floors[0].runs = [] (or floors[i].runs = [] , if you're looping through), then those two empty arrays would no longer show up in your stringify.

Editing my answer, to match the OP edits:

floors.forEach(function(floor){
   var newRuns = [];
   floor.runs.forEach(function(run){
       if (run.length > 0){
           newRuns.push(run);
       }
   })
   floor.runs = newRuns;
})

After I assign your object from the OP into a variable and run my code on it, then stringify the result, I get this as a return:

{"floors":[{"floorName":"Grd Floor","floorNotes":"","floorPlan":"Buckley_Grd.jpg","floorWidth":"57.392","floorHeight":"20.776","runs":[[{"xCoOrd":"37.88235294117647","yCoOrd":"59.307359307359306","drawingType":"node"},{"xCoOrd":"37.88235294117647","yCoOrd":"59.307359307359306","drawingType":"node"},{"xCoOrd":"48.549019607843135","yCoOrd":"50","drawingType":"node"}]]}]}

Is that what you're hoping to see? I used this fiddle to produce that result.

If you want remove ALL values from runs array you simply do this:

floors[i].runs = null

If you want remove only the empties

var filled = [];
obj.floors[i].runs.forEach(function(value, i, array) {
    if (value.length != 0) filled.push(value);
});

obj.floors[i].runs = filled;

Runs is a property of an object, you can remove items from that array. In your example above floors[0].runs.splice(0,2), should remove both of those arrays I think.

Keeping the same reference

Iterating downwards lets you safely perform operations which decrease the length of an Array by 1 each time

var i, parentArray = obj['floors'][0]['runs'];
for (i = parentArray.length; i >= 0; --i) {
    if (parentArray[i].length === 0) parentArray.splice(i, 1);
}

Making a new reference

Creating a new array without the values you don't want can be achieved using .filter

obj['floors'][0]['runs'] = obj['floors'][0]['runs'].filter(function (x) {
    return x.length > 0;
});

To remove an object completely you have to remove the reference from the parent. To do this what you can do is create a new Array in which you copy only the references to the non-empty arrays.

I have created this function which should remove all empty arrays. I haven't tested it too much, but this should give you an idea:

function clearEmptyArrays(obj) {
   for(var key in obj) {

    var arr = obj[key];

    if(Array.isArray(arr)) {
      // Iterate through all elements and remove empty arrays
      var nonEmptyArr = [];
      for(var i = 0; i < arr.length; ++i) {
        // Recursive call if it's an object inside an array
        if(typeof arr[i] === 'object') clearEmptyArrays(arr);

        // Save all non-empty arrays or objects inside this one
        if((Array.isArray(arr[i]) && arr[i].length > 0) || !Array.isArray(arr[i])) {        
            nonEmptyArr.push(arr[i]);
         }
      }

      obj[key] = nonEmptyArr;
      return;
    }

    // Recursive call if it's an object
    if(typeof arr === 'object') {
        clearEmptyArrays(arr);
    }
  }
}

You can call it like this: clearEmptyArrays(myObj); and will update the Object in-place.

Demo: https://jsfiddle.net/zeo7dauh/

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