ホームページ >ウェブフロントエンド >jsチュートリアル >「ホール」の真実: JavaScript の疎な配列と予期しない動作を理解する
私は最近、データ構造とアルゴリズム、特に並べ替えアルゴリズムのスキルを磨いていました。そして私は興味深い状況に陥っていることに気づきました。
並べ替えアルゴリズムをテストするために、長さ n の値のランダムな配列を作成するにはどうすればよいですか?それは簡単だと思われるかもしれませんが、本当にその通りです。あなたの頭の中で、おそらく次のようなことを思いついたでしょう:
function randomArray(n) { const arrToReturn = []; for (let i = 0; i < n; i++) { arrToReturn.push(Math.floor(Math.random() * 10)); } return arrToReturn; }
これは間違いなく意図したとおりに機能します。しかし、私はもっとシンプルなものを探していました。できればワンライナーで。さて、最初に思いついたのは new Array() を使用することでした。
const randomArray = (n) => new Array(n).map(() => Math.floor(Math.random() * 10)); console.log(randomArray(5))
これは何をログに記録すると思いますか?
そうですね、私はこれがランダムな 5 つの値の配列を記録することを期待していました。そうでなかったら、乾杯!私がこれから何を話そうとしているかご存知でしょう:)
驚いたことに、そうではありません。これをノード 20 に記録します:
[ > ]
うーん...不可解!
興味深いことに、console.log(randomArray(5).length) は 5 を記録します。
では、なぜこのようなことが起こるのでしょうか?それでは、JavaScript のスパース配列について話しましょう!
疎配列は、1 つ以上の空のスロットを含む配列です。例:
new Array(2) // [<2 empty items>] [1, , , 3] // [1, <2 empty items>, 3]
それで、これはどのように機能するのでしょうか?
JS で new Array(5) を使用して配列を作成すると、5 つの初期化されていないスロットを持つ配列が作成されます。これは、それらには何も含まれていないことを意味します。 null ではなく、未定義でもありません。
わかりました、わかりました!しかし、それらの「スロット」で .map を呼び出すことはできませんか?
スパース配列に対して forEach、map、reduce、filter などの反復メソッドを呼び出すと、これらの空のスロットはスキップされます。
関数randomArrayをもう一度見てみましょう。
const randomArray = (n) => new Array(n).map(() => Math.floor(Math.random() * 10));
new Array(n) を使用して長さ n の配列を作成し、スパース配列 [] を返します。次に、その配列に対して map を呼び出します。すべてのスロットが空であるため、すべてスキップされます。したがって、得られた結果は次のとおりです!
これは、JS での .length 配列メソッドの実装方法が原因です。長さの値を取得するには、最大のインデックスを取得し、1 を加算するだけです。また、疎配列にはインデックスが付けられているため、期待どおりの長さの値が得られます。詳細はこちらでご覧いただけます。
スパース配列には空のスロットまたは初期化されていないスロットが含まれているため、反復可能ではありません。これらのスロットに値を入力することでこの問題を修正できます。これは、.fill 配列メソッドを使用することで実現できます。
const randomArray = (n) => new Array(n).fill().map(() => Math.floor(Math.random() * 10)); console.log(randomArray(5))
それでは、準備完了です!
以上が「ホール」の真実: JavaScript の疎な配列と予期しない動作を理解するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。