エントリがまばらな要素の配列があります。データをループするたびに null や未定義の値をチェックし続ける必要がないように、疎な配列を密集した配列に簡単に圧縮するにはどうすればよいですか?
以下にデータの例を示します。
var sparse = [];
sparse[1] = undefined;
sparse[5] = 3;
sparse[10] = null;
var dense = sparseToDenseArray(sparse);
// dense should be [3]
エントリがまばらな要素の配列があります。データをループするたびに null や未定義の値をチェックし続ける必要がないように、疎な配列を密集した配列に簡単に圧縮するにはどうすればよいですか?
以下にデータの例を示します。
var sparse = [];
sparse[1] = undefined;
sparse[5] = 3;
sparse[10] = null;
var dense = sparseToDenseArray(sparse);
// dense should be [3]
filter()
Firefox、Chrome、IE 9、Opera、および Safari Web ブラウザーと互換性のあるものを使用できます。
David Flanagan によると、Javascript: The Definitive Guideでは、疎配列を密配列に変換する簡単な方法は、次のようにフィルターを使用することです。
var dense = sparse.filter(function (x) { return x !== undefined && x != null; });
filter()
不足している要素をスキップしtrue
、 x がundefined
またはでない場合にのみ返すため、これは機能します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]);
バニラ 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 を含めたい場合は、配列でコンパクト関数を使用できます。
ここに非常に限られた答えがあるとは信じられません。まず第一に、スパース配列を圧縮するためのより良い、より高速なソリューションがあると思います。まばらな配列は、未定義の項目の穴がある配列を意味するものではないと思います (密集した配列とは正確には何ですか? )。スパース配列は、既存のスパース値に属するキー以外に実際にはキーが存在しない配列である必要があります。したがって、キーを反復処理すると、仕事をより効率的かつ迅速に行うことができます。
OK、以下のテストをコンパイルして、スパース配列を圧縮するいくつかの方法のパフォーマンスを示しました。
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;
});