Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

環境

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))
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away