Panda Noir

JavaScript の限界を究めるブログでした。最近はいろんな分野を幅広めに書いてます。

ワンライナーで[1..100]を生成する in JavaScript

0で埋まった配列はArray(100).fill(0)でおしまいですが、[1..100]となると生のJavaScriptでは実は考えないとできません。

ツイッターで少し(空中リプで)議論したのでそのまとめしつつ思いついたものを書きます。

あらまし

このツイートを発見した私

https://twitter.com/le_panda_noir/status/681708160969670656

まあパフォーマンス考えると良い手打ってます(実は一番ではなかった)。わかりやすさも抜群です。

もうちょっとこの後改善しました

https://twitter.com/le_panda_noir/status/681717459926138880

これに対しがおさん

目からウロコですね。

軽く解説

最初のAyaさんのコードと私のコードは解説いりませんよね?まんまです。mapのコールバック関数の第二引数が添字になってるということだけ少しわかりづらいですかね。

がおさんのコードは結構最適化してますね。

演算子ノ全テ - Panda Noirを見るとさらに理解が深まります(宣伝)。

順にコードを追いかけるとまず–iが評価されiが一つ減ります(i==99)。減らした後、–iは99となります(arr[99]=i)。

そしてarr[99]=iが評価されarr[99]=99となりarr[99]に99が代入され、arr[99]=99は99となります。

99はtruthyなのでループは続きます。ちなみにはじめてfalsyとなるのは0なのでそれまでループは続きます。

ワンライナー縛りなしでしてみる

ワンライナー縛りでしたが、なしだとGenerator使ってこんなこともできます。

function* iter() {
    var i = 1;
    while(true) {
        yield i++;
    }
}
iter.take(100);

とここでGeneratorにtakeがないと気づきました。仕方ないので拡張します

Generator.prototype.take = function(n) {
    var res = [];
    for (let i of this()) {
        if (n--) break;
        res.push(i);
    }
    return res;
};

(注: パソコン起動してないので上のtake()は実際に動作確認してません。あくまでpseudoコードです)

これで上のコードで[1..100]を取得できます。短く直感的でなかなか気に入ってます。

終わりに

意外と使う場面がありますが、ワンライナーで綺麗に書けないのがもどかしかったです。

実際必要な時はだいたいlodashの_.range()使いますがね(笑)。