简体   繁体   中英

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?

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.

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 :)

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 ;
}

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