Sam
Sam

Reputation: 313

Most efficient way to delete from array?

I have an array containing particles (fire, blood, smoke, etc.) in an HTML5 game. All particles have an expiry/lifespan. I'm creating up to 100 particles per frame at 60fps so I want to keep this array as clean as possible so I can loop through it efficiently.

I have heard it's better to use 'splice' rather than 'delete' to remove elements from an array. This makes sense to me as I'd rather not loop through keys of the array that are blank (that 'delete' leaves behind).

However, I tested this out and have a higher, more consistent frame rate if I 'delete' keys rather than splicing them to remove expired particles. The downside is the longer the game runs the longer my particles array gets.

Is there a better solution to this?

Upvotes: 4

Views: 6108

Answers (3)

GameAlchemist
GameAlchemist

Reputation: 19294

You'll have way higher performances by packing the array by yourself : less operations AND no need to dispose current array and create a new one (like Array.filter does), so much less garbage collection.

function packArray(tgtArray) {
   if (!tgtArray || !tgtArray.length) return;
   var srcIndex = 0;
   var dstIndex = 0;
   var arrayLength = tgtArray.length ;
   do {
       var currentItem = tgtArray[srcIndex]; 
       if (currentItem.alive) {
         if (srcIndex != dstIndex) {
            tgtArray[dstIndex] = currentItem ;
         }
         dstIndex++;
       } 
       srcIndex++;
   } while (srcIndex != arrayLength) ;
    dstIndex--;
    tgtArray.length = dstIndex > 0 ? dstIndex : 0 ;
}

Upvotes: 1

user3886234
user3886234

Reputation:

When you use delete on an array element, all you are actually doing is setting that array element to undefined. The array will still have the same length. When you use splice, you actually remove that element entirely. The element is removed, and everything after that element is shifted down 1 index.Of the two, delete is going to be faster since your array doesn't have to re-index.

As for performance, if leaving the deleted elements as undefined works, then that is probably the best way to do it. If you are concerned about the array length growing too long, or maybe have to search that array frequently and want to reduce overhead, you could periodically filter out the undefined elements like so:

function filterArr() {
    myArr = myArr.filter(function(v) {
       return typeof v !== 'undefined';
    });
}

var interval = setInterval(filterArr, 5000);

This will give you the best of both worlds. When you need to remove the particles, you use delete to set the elements to undefined, which is faster than removing them in place. Every now and then, you remove them in place to keep your array size lower.

You could improve upon that depending on your requirements. Good luck :)

Upvotes: 2

six fingered man
six fingered man

Reputation: 2500

If the order of the items in the array doesn't matter, then simply assign the last item in the array to the one you want to overwrite and then delete it by reducing the .length.

function unordered_remove(arr, i) {
    if (i <= 0 || i >= arr.length) {
        return;
    }
    if (i < arr.length - 1) {
        arr[i] = arr[arr.length-1];
    }
    arr.length -= 1;
}

This is much faster because it doesn't need to reindex and is good for situations where the order doesn't matter.

Upvotes: 4

Related Questions