簡體   English   中英

在 Javascript 中壓縮稀疏數組?

[英]Condensing a sparse array in Javascript?

我有一個元素數組,其中條目稀疏。 如何輕松地將稀疏數組壓縮為密集數組,以便每次遍歷數據時都不必繼續檢查 null 和 undefined 值?

以下是一些示例數據:

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

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

您可以使用與 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 不是undefinednull時才返回true

如果不支持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]);

在 ES2017 (ES8) 中,這和Object.values(sparseArray)一樣簡單

例如:

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

請注意,此方法僅刪除gaps ,根據需要向下移動現有數組元素的索引。 它不會刪除顯式設置為undefinednull元素。

在 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函數。

我不敢相信這里的答案如此有限。 首先,我認為有更好、更快的解決方案來壓縮稀疏數組。 我猜一個稀疏數組並不意味着一個帶有未定義項孔的數組(究竟什么是密集數組? )。 稀疏數組應該是一個數組,其中除了屬於現有但稀疏值的鍵之外,實際上不存在任何鍵。 因此,如果我們迭代鍵,我們應該更有效、更快地完成我們的工作。

好的,我在下面編譯了一個測試,向您展示了幾種壓縮稀疏數組的方法的性能。

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

演示。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM