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

Most efficient way to delete from array?

本文关键字:有效 方法 删除 数组      更新时间:2023-09-26

我有一个包含HTML5游戏中粒子(火,血,烟等(的数组。所有粒子都有有效期/寿命。我以 60fps 的速度每帧创建多达 100 个粒子,所以我想让这个数组尽可能干净,这样我就可以有效地循环播放它。

我听说最好使用"拼接"而不是"删除"从数组中删除元素。这对我来说很有意义,因为我宁愿不循环遍历数组的空白键("删除"留下(。

但是,我对此进行了测试,如果我"删除"键而不是拼接它们以删除过期的粒子,则具有更高,更一致的帧速率。缺点是游戏运行的时间越长,我的粒子数组就越长。

有没有更好的解决方案?

如果数组中项目的顺序无关紧要,则只需将数组中的最后一个项目分配给要覆盖的项目,然后通过减少.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;
}

这要快得多,因为它不需要重新索引,并且适用于顺序无关紧要的情况。

当您在数组元素上使用 delete 时,您实际要做的就是将该数组元素设置为 undefined 。 数组仍将具有相同的长度。 当你使用splice时,你实际上完全删除了该元素。 该元素被删除,该元素之后的所有内容将向下移动 1 个索引。在这两者中,delete会更快,因为您的数组不必重新索引。

至于性能,如果将删除的元素保留为undefined有效,那么这可能是最好的方法。 如果您担心数组长度过长,或者可能必须频繁搜索该数组并希望减少开销,则可以定期filter出未定义的元素,如下所示:

function filterArr() {
    myArr = myArr.filter(function(v) {
       return typeof v !== 'undefined';
    });
}
var interval = setInterval(filterArr, 5000);

这将为您提供两全其美的效果。 当您需要删除粒子时,您可以使用delete将元素设置为 undefined,这比就地删除它们更快。 时不时地将它们删除以保持较低的阵列大小。

您可以根据自己的要求对其进行改进。 祝你好运:)

通过自己打包数组,您将获得更高的性能:更少的操作,无需处理当前数组并创建一个新数组(如 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 ;
}