假设您有一个JavaScript数组。
var a = []
然后用1000万个值(任意值,例如字符串,整数,布尔值,浮点数,甚至dom元素)填充此数组。
a == [ 1, true, false, 2.2, 'hello world', 3.3, 1, 'foo', ... ]
然后,您可以从阵列中的任意位置删除一堆项目。
a == [ 1, undefined, false, undefined, undefined, 3.3, 1, undefined, ... ]
因此,数组中现在似乎有随机放置的空插槽。
在我进一步讨论之前,问题是如何将剩余的元素压缩/捆绑/分组到(可能是新的)数组中,从而使它们占用最小的空间,但是却不需要太多的处理力量/时间来确定如何重新排列数组中的项目。我们可以在合理的范围内拥有尽可能多的关于数组的元数据来存储东西,但是当它重新分配数组时,它如此有效。我正在考虑同时运行具有多个图形应用程序的浏览器,所以它应该是高效的。
更深入一点,我使用此系统进行的第一个优化是跟踪从数组中删除的项的索引,只需执行a[i] = undefined
而不是a.splice(i, 1)
。如果您添加一项,然后删除一项,然后添加n项,然后删除n项,则效果很好,因为undefined
插槽会被新项重新填充(如果要快速添加/删除)。>
但是,如果您拥有1000万个项目,然后随机删除其中一百万个项目,则此操作将分解。现在,我们有了一个二级索引来跟踪100万个未使用的索引和100万个undefined
插槽,因此该阵列占用了不需要的内存(附带说明,如果v8将其优化,则只需考虑Uint8Array或类似的方法,在这种情况下,我很确定所有这些未定义的变量(如果为Uint8Array赋值为0,则为零)将占用空间。
因此,目标是以某种可能的最佳方式遍历数组 (请记住,我们可以拥有有关数组的元数据来帮助进行处理)以重新组织并保存在空间上,同时仍然是一种快速算法,并且不使用大量临时内存。我不知道,但这似乎是一个难题,所以我真的不知道最好去哪里。
我不想一直重新创建数组并遍历整个数组并跳过所有未定义的数组。我想要某种东西,也许以某种方式将被间隙分开的项目放入更整齐的块中,然后将它们压向阵列的开头,直到那时我们才意识到现在我们可以删除10000个插槽,并且然后创建一个新的数组,该数组要短10000。那种东西。因此,听起来很不错的一种启发式方法是,每当有10000个空插槽时就重新创建阵列。但我不确定是否就这么简单。