简体   繁体   English

在 Javascript 中压缩稀疏数组?

[英]Condensing a sparse array in Javascript?

I have an array of elements where the entries are sparse.我有一个元素数组,其中条目稀疏。 How can I easily condense the sparse array into a dense array so that I don't have to keep checking for null and undefined values every time I loop through the data?如何轻松地将稀疏数组压缩为密集数组,以便每次遍历数据时都不必继续检查 null 和 undefined 值?

Here is some example data:以下是一些示例数据:

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

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

You can use filter() which is compatible with Firefox, Chrome, IE 9, Opera, and Safari web browsers.您可以使用与 Firefox、Chrome、IE 9、Opera 和 Safari 网络浏览器兼容的filter()

According to David Flanagan, in Javascript: The Definitive Guide , an easy way of transforming a sparse array to a dense array is to use a filter on it like so:根据 David Flanagan 的说法,在Javascript: The Definitive Guide 中,将稀疏数组转换为密集数组的一种简单方法是在其上使用过滤器,如下所示:

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

This works since filter() skips missing elements and only returns true if x is not undefined or null .这是有效的,因为filter()跳过缺少的元素,并且仅在 x 不是undefinednull时才返回true

If filter() is not supported, this will compact a sparse array:如果不支持filter() ,这将压缩一个稀疏数组:

var compacted = [];

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

An exact equivalent of the filter() example is: filter()示例的完全等效项是:

var compacted = [];

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

In ES2017 (ES8) this is as easy as Object.values(sparseArray)在 ES2017 (ES8) 中,这和Object.values(sparseArray)一样简单

For example:例如:

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

Note though that this method only removes gaps , shifting down the indexes of existing array elements as required.请注意,此方法仅删除gaps ,根据需要向下移动现有数组元素的索引。 It does not remove elements explicitly set to undefined or null .它不会删除显式设置为undefinednull元素。

In vanilla JS, works on all browsers:在 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]

如果你想在你的代码中包含 underscore.js,你可以在你的数组上使用compact函数。

I can't believe there is so limited answers in here.我不敢相信这里的答案如此有限。 First of all i think there are better, faster solutions to condensing a sparse array.首先,我认为有更好、更快的解决方案来压缩稀疏数组。 I guess a sparse array doesn't mean an array with holes of undefined items ( What exactly is a dense array? ).我猜一个稀疏数组并不意味着一个带有未定义项孔的数组(究竟什么是密集数组? )。 A sparse array should be an array where actually there are no keys exists other than the keys which belong to the existing but sparse values.稀疏数组应该是一个数组,其中除了属于现有但稀疏值的键之外,实际上不存在任何键。 So if we iterate over the keys we should be doing our job more efficiently and faster.因此,如果我们迭代键,我们应该更有效、更快地完成我们的工作。

Ok i compiled a test below to show you the performance of several methods to condense a sparse array.好的,我在下面编译了一个测试,向您展示了几种压缩稀疏数组的方法的性能。

 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");

filter is a JavaScript extension to the ECMA-262 standard; filter 是 ECMA-262 标准的 JavaScript 扩展; as such it may not be present in other implementations of the standard.因此,它可能不会出现在标准的其他实现中。 You can work around this by inserting the following code at the beginning of your scripts, allowing use of filter in ECMA-262 implementations which do not natively support it.您可以通过在脚本的开头插入以下代码来解决此问题,允许在本机不支持它的 ECMA-262 实现中使用过滤器。 Reference : MDN .参考: MDN

A cross browser solution using filter使用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.演示。

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

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