LoginSignup
63
46

More than 5 years have passed since last update.

【JavaScript】配列を同じ値で埋めたり、連続した値を設定する

Last updated at Posted at 2018-01-29

環境

google chrome
TypeScript2.6を使用しています。

配列を同じ値で埋める方法

Array.prototype.fill()を使ったコード

const len: number = 10;      // 作りたい配列の長さ
const el: string = 'foo';    // 埋めたい値
const ary = new Array<string>(len).fill('foo');

console.log(ary.join(','));    // foo,foo,foo,foo,foo,foo,foo,foo,foo,foo

以下のようにArrayのコンストラクターは引数が数値一つだけの場合、その長さを持った配列を作ります。

const ary1 = [3];    // 3という要素を持つ配列

const ary2 = new Array(3);    // 長さが3の配列

const ary3 = new Array(3, 6, 88, 1);    // 長さが4の配列

fill()メソッドは、配列中の開始インデックスから終了インデックスまでの要素を固定値で設定します。
第1引数には設定する値、第2引数には開始インデックス、第3引数には終了インデックスを指定します。
第2、第3引数を省略すると配列にすべて同じ値を設定します。

Array.prototype.fill()を使わないコード

const len: number = 10;
const word: string = 'foo';

const ary = new Array<string>(len);
for (let i = 0, len = ary.length; i < len; i++) {
    ary[i] = word;
    // ary.push(word);
}

上記のコードではforループを使って各要素に値を代入もしくは順にpush()しています。
繰り返す回数の指定やインデックスなどバグが入り込みやすくなるので非推奨です。

配列に連続した値を設定する方法

Array.prototype.map()を使った方法

const len: number = 10;
const sequential = new Array(len)
    .fill(null)
    .map((_, i) => i);

console.log(sequential.join(','));    // 0,1,2,3,4,5,6,7,8,9

まず、任意の長さを持つ配列を作り、fill()で各要素を埋めます。
map()のcallback関数に渡される第1引数には現在処理中の要素、第2引数には現在処理中の要素のインデックスが渡されます。
途中のfill()は省略できないので以下のようには書けません。
理由をご存知の方がいらっしゃたら教えてください。

const len: number = 10;
const sequential = new Array(len)
    .map((_, i) => i);

以下のように書くと0以外から連番を開始することもできます。

const len: number = 10;
const sequential = new Array(len)
    .fill(1)               // 1で埋めて
    .map((n, i) => n + i); // 1 + インデックスで要素をマッピングした新しい配列を作る

console.log(sequential.join(','));    // 1,2,3,4,5,6,7,8,9,10
const len: number = 10;
const sequential = new Array(len)
    .fill(null)
    .map((_, i) => i + 20);    // 処理中のindex + 任意の値
console.log(sequential.join(','));    // 21,22,23,24,25,26,27,28,29,30

Array.prototype.map()を使わない方法

const len: number = 10;

const sequential = new Array<number>(len);
for (let i = 0, len = sequential.length; i < len; i++) {
    sequential[i] = i;
    // sequential.push(i);
}

console.log(sequential.join(','));

同じ値で要素を埋める場合と同じように実装します。
forループを使ったコードが先ほどの通り、バグが入り込む可能性が上がるので非推奨です。

Array.prototype.from() を使った方法

コメントで Array.prototype .from を使用した連続した値の生成方法を教えていただいたのでFizzBuzz問題に使用してみました。

class FizzBuzz {
    private numbers: number[] = [];

    constructor(range: {
        start: number,
        end: number
    }) {
        this.numbers = Array.from(
            { length: (range.end - range.start + 1) },
            (v, k) => k + range.start);
    }

    public exec(): string[] {
        return this.numbers.map(n => this.getWord(n))
    }

    private getWord(n: number): string {
        let word: string = '';
        if (n % 3 === 0) {
            word += 'Fizz';
        }
        if (n % 5 === 0) {
            word += 'Buzz'
        }
        return word === '' ? n.toString() : word;
    }
}

const fb = new FizzBuzz({ start: 1, end: 100 });
fb.exec().forEach(s => console.log(s))
63
46
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
63
46