できればより高速な双方向indexOf
/lastIndexOf
代替
2015年
新しいメソッドインクルードは非常に優れていますが、現時点ではサポートは基本的にゼロです。
遅い indexOf/lastIndexOf 関数を置き換える方法を考えていたのは長い間です。
上位の回答を見ると、パフォーマンスの高い方法がすでに見つかっています。それらの中からcontains
、@Damir Zekic によって投稿された最も速い関数を選びました。しかし、ベンチマークは2008年のものであり、時代遅れであるとも述べています.
私も よりも好きですwhile
がfor
、特別な理由はありませんが、 for ループを使用して関数の記述を終了しました。で行うこともできますwhile --
。
実行中に配列の両側をチェックすると、反復がはるかに遅くなるかどうかに興味がありました。どうやらいいえ、したがって、この関数は上位投票のものよりも約 2 倍高速です。明らかに、ネイティブよりも高速です。これは、検索している値が配列の先頭にあるのか末尾にあるのかがわからない現実世界の環境です。
配列に値をプッシュしたことがわかっている場合は、おそらく lastIndexOf を使用することが最善の解決策ですが、大きな配列を移動する必要があり、結果がどこにでもある可能性がある場合、これは物事を高速化するための確実な解決策になる可能性があります。
双方向 indexOf/lastIndexOf
function bidirectionalIndexOf(a, b, c, d, e){
for(c=a.length,d=c*1; c--; ){
if(a[c]==b) return c; //or this[c]===b
if(a[e=d-1-c]==b) return e; //or a[e=d-1-c]===b
}
return -1
}
//Usage
bidirectionalIndexOf(array,'value');
性能テスト
http://jsperf.com/bidirectionalindexof
テストとして、100k エントリの配列を作成しました。
3 つのクエリ: 配列の先頭、中間、末尾。
これも興味深いものであり、パフォーマンスをテストしていただければ幸いです。
注: ご覧のとおりcontains
、indexOf と lastIndexOf の出力を反映するように関数を少し変更しました (基本的true
にindex
とfalse
を使用-1
)。それはそれを害するべきではありません。
配列のプロトタイプ バリアント
Object.defineProperty(Array.prototype,'bidirectionalIndexOf',{value:function(b,c,d,e){
for(c=this.length,d=c*1; c--; ){
if(this[c]==b) return c; //or this[c]===b
if(this[e=d-1-c] == b) return e; //or this[e=d-1-c]===b
}
return -1
},writable:false, enumerable:false});
// Usage
array.bidirectionalIndexOf('value');
この関数は、true または false、さらにはオブジェクト、文字列などを返すように簡単に変更することもできます。
そして、ここにwhile
バリアントがあります:
function bidirectionalIndexOf(a, b, c, d){
c=a.length; d=c-1;
while(c--){
if(b===a[c]) return c;
if(b===a[d-c]) return d-c;
}
return c
}
// Usage
bidirectionalIndexOf(array,'value');
これはどのように可能ですか?
配列内の反映されたインデックスを取得する単純な計算は非常に単純であるため、実際のループ反復を実行するよりも 2 倍高速であると思います。
これは反復ごとに 3 つのチェックを行う複雑な例ですが、これはコードの速度低下の原因となるより長い計算でのみ可能です。
http://jsperf.com/bidirectionalindexof/2