简体   繁体   English

从数组中删除最有效的方法?

[英]Most efficient way to delete from array?

I have an array containing particles (fire, blood, smoke, etc.) in an HTML5 game. 我在HTML5游戏中有一个包含粒子(火,血,烟等)的数组。 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. 我每帧以60fps创建多达100个粒子,所以我希望尽可能保持这个阵列的清洁,这样我就可以有效地循环它。

I have heard it's better to use 'splice' rather than 'delete' to remove elements from an array. 我听说最好使用'splice'而不是'delete'来删除数组中的元素。 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 . 如果数组中项目的顺序无关紧要,则只需将数组中的最后一项指定给要覆盖的项目,然后通过减少.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 . 在数组元素上使用delete时,实际上所做的就是将该数组元素设置为undefined The array will still have the same length. 该数组仍将具有相同的长度。 When you use splice , you actually remove that element entirely. 当您使用splice ,实际上您完全删除了该元素。 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. 该元素被删除,并且该元素之后的所有内容都向下移动1个索引。如果这两个元素, delete将更快,因为您的数组不必重新索引。

As for performance, if leaving the deleted elements as undefined works, then that is probably the best way to do it. 至于性能,如果将删除的元素保留为undefined工作,那么这可能是最好的方法。 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: 如果您担心数组长度增长太长,或者可能需要经常搜索该数组并希望减少开销,您可以定期filter掉未定义的元素,如下所示:

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. 当您需要删除粒子时,使用delete将元素设置为undefined,这比在适当位置删除它们更快。 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. 通过自己打包数组,你将获得更高的性能:更少的操作,不需要处理当前数组并创建一个新数组(如Array.filter那样),因此垃圾收集更少。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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