うならぼ

申し訳程度のアフィリエイトとか広告とか解析とかは/aboutを参照

JSで1..Nの総和を計算する、もしくは要素数Nの配列を作る

ask.fm

Haskellで書いて短いのはともかく、JSのコードがなんとも。

探してみると Array.prototype.reduce() があった。ちゃんと要素のインデックスも渡してくれるので、これを順に足しこめばいける。

あとは要素数Nの配列をどうするか。Array(100) とすればundefinedが100個並んだ配列が・・・できない。

Javascriptの配列はインデックスをキーとしたオブジェクトなので、通常100要素の配列というと

{ 0: undefined, 1: undefined, ..., 99: undefined, length: 100 }

といったオブジェクトになる。一方 Array(100) で生成されるのはこんなやつ。

{ length: 100 }

何が問題かって、この歯抜け部分は Array.prototype.map() や肝心の Array.prototype.reduce() で無視されてしまう。 Int8Array などの型付けされた配列を使えば各要素が0で初期化されるけど、普通のArrayでやる方法はないものか。

Create a JavaScript array containing 1...N - Stack Overflow

Array.apply(null, { length: 100 })
// もしくは
Array.apply(null, Array(100))

Function.prototype.apply() の第二引数はその関数に渡す引数の配列。そこに長さ100の(歯抜け)配列を渡しているので、 Array() は引数100個指定されたものと思い込み、100個の引数を順番にセットした配列を作ってくれると。賢いなー。

というわけで、「1から114514まで足し算した結果をalertするプログラム」はこちら。

alert(new Int8Array(114514).reduce(function(p, c, i){ return p + i }, 0))
// もしくは
alert(Array.apply(null, Array(114514)).reduce(function(p, c, i){ return p + i }, 0))

どっちにしても長い。

追記:ES6だったら Array.prototype.keys()を使うのもよさげ。添え字が値になるし。返り値はIteratorなので、Array.from(Array(100).keys()) とか [...Array(100).keys()] とか。

alert([...Array(100).keys()].reduce((p,c) => p + c, 0))

LINQなら keys().reduce(...) ってできそうなのにというあれ。