在Javascript中压缩稀疏数组?

时间:2012-07-25 23:16:37

标签: javascript arrays sparse-array

我有一个元素数组,其中条目是稀疏的。如何轻松地将稀疏数组压缩为密集数组,以便每次循环数据时都不必继续检查null和undefined值?

以下是一些示例数据:

var sparse = [];
sparse[1] = undefined;
sparse[5] = 3;
sparse[10] = null;

var dense = sparseToDenseArray(sparse);
// dense should be [3]

6 个答案:

答案 0 :(得分:11)

您可以使用与Firefox,Chrome,IE 9,Opera和Safari网络浏览器兼容的filter()

根据David Flanagan的说法,在 Javascript:The Definitive Guide 中,将稀疏数组转换为密集数组的简单方法是在其上使用过滤器,如下所示:

var dense = sparse.filter(function (x) { return x !== undefined && x != null; });

这是有效的,因为filter()会跳过缺少的元素,只有当x不是trueundefined时才会返回null

如果不支持filter(),则会压缩稀疏数组:

var compacted = [];

for(var i = 0; i < sparse.length; i++)
    if(i in sparse)
        compacted.push(sparse[i]);

filter()示例的完全等价物是:

var compacted = [];

for(var i = 0; i < sparse.length; i++)
    if(sparse[i] != null)
        compacted.push(sparse[i]);

答案 1 :(得分:5)

在ES2017(ES8)中,这就像Object.values(sparseArray)

一样简单

例如:

&#13;
&#13;
const sparseArray = [, , 'foo', 'bar', , 'baz', ,];
const compactArray = Object.values(sparseArray);
console.log(compactArray);
&#13;
&#13;
&#13;

请注意,此方法仅删除 gap ,根据需要向下移动现有数组元素的索引。它不会删除明确设置为undefinednull的元素。

答案 2 :(得分:2)

如果要在代码中包含underscore.js,可以使用阵列上的compact函数。

答案 3 :(得分:1)

在vanilla JS中,适用于所有浏览器:

function filt(a) { 
 var b = []; 
 for(var i = 0;i < a.length;i++) { 
  if (a[i] !== undefined && a[i] != null) { 
   b.push(a[i]); 
  }
 } 
 return b; 
}

> filt([1,undefined,3])
[1, 3]

答案 4 :(得分:1)

我无法相信这里的答案非常有限。首先,我认为有更好,更快的解决方案来缩小稀疏阵列。我猜一个稀疏数组并不意味着一个带有未定义项目空洞的数组(What exactly is a dense array?)。稀疏数组应该是一个数组,其中除了属于现有但稀疏值的键之外,实际上不存在任何键。因此,如果我们迭代密钥,我们应该更有效,更快地完成工作。

好的,我在下面编译了一个测试,向您展示了几种压缩稀疏数组的方法的性能。

&#13;
&#13;
var ts = 0,
    te = 0,
sparse = new Array(10000000),
 dense = [];
[sparse[2499999], sparse[4999999], sparse[9999999]] = ["first one", "middle one", "last one"];

ts = performance.now();
dense = Object.keys(sparse).map(k => sparse[k]);
te = performance.now();
console.log(dense, "Okeys and map resulted in :" +(te-ts)+ "msecs");

dense = [];

ts = performance.now();
for (var key in sparse) dense.push(sparse[key]);
te = performance.now();
console.log(dense, "for in loop resulted in :" +(te-ts)+ "msecs");

dense = [];

ts = performance.now();
dense = sparse.filter(function (x) { return x !== undefined && x !== null; });
te = performance.now();
console.log(dense, "Array filter resulted in :" +(te-ts)+ "msecs");

dense = [];

ts = performance.now();
for (var i = 0, len = sparse.length; i < len; i++) sparse[i] !== undefined &&
                                                   sparse[i] !== null      &&
                                                   dense.push(sparse[i]);
te = performance.now();
console.log(dense, "For loop resulted in :" +(te-ts)+ "msecs");
&#13;
&#13;
&#13;

答案 5 :(得分:0)

  

filter是ECMA-262标准的JavaScript扩展;就这样吧   可能不存在于该标准的其他实现中。您可以   通过在开头插入以下代码来解决这个问题   你的脚本,允许在ECMA-262实现中使用过滤器   不要原生支持它。参考:MDN

使用filter

的跨浏览器解决方案
if (!Array.prototype.filter) {  // Add the filter method to the 'Array prototype' if it's not available
    Array.prototype.filter = function(fun /*, thisp*/) {
        var len = this.length >>> 0;
        if (typeof fun != "function") {
            throw new TypeError();
        }

        var res = [];
        var thisp = arguments[1]; 
        for (var i = 0; i < len; i++) {
            if (i in this) {
                var val = this[i];
                if (fun.call(thisp, val, i, this)) {
                    res.push(val);
                }
            }
        }
        return res;
    };
}

var sparse = [];
sparse[1] = undefined;
sparse[5] = 3;
sparse[10] = null;

dense=sparse.filter(function(a){ //Call the `filter` method
    return a!== undefined && a != null;
});

DEMO.