LoginSignup
5
3

More than 3 years have passed since last update.

for文を使わないでやってみた

Last updated at Posted at 2020-03-29

はじめに

for文は色々な言語で用意されており、様々なところで使われています。
実際、同じ処理を複数回するときに便利です。
また、for文が使われていれば、容易に繰り返し同じことをしていると分かります。
簡単であり、可読性が高いという点で、for文は優れていると思います。

しかし、それは処理という面で捉えるからです。
オブジェクトという面で見たときは、拡張for文の登場によって扱えるとは言え、優れているとは言えないでしょう。
JavaScriptにはちゃんと Array というビルドインオブジェクトが用意されているので、それを使って繰り返す処理を書くことも選択肢に入れましょう。

という訳で、今回はfor文からArrayを使った書き方に移行する方法を紹介していきたいと思います。

指定回数繰り返す

10回ログに出力します。

// for文
for(let i=0; i<10; i++) {
    console.log('repeat:', i);
}


// Array
[...Array(10)].forEach((_, i) => {
    console.log('repeat:', i);
});

[...Array(10)] のようにすることで、固定長の配列を作成することができます。

ここで使っているのは、 Array.prototype.forEach() です。
与えられた配列の中身を順番に実行して、新しく配列を生成する必要の無い場合は、これを使うことができます。

指定範囲の配列を作成する

1から10までの2つおきの配列を作成します。

// for文
const vFor = [];
for(let i=1; i<=10; i+=2) {
    vFor.push(i);
}
console.log(vFor); // [ 1, 3, 5, 7, 9 ]


// Array
const range = (start: number, stop: number, step: number) => {
    return Array.from({ length: (stop - start) / step + 1}, (_, i) => start + (i * step));
}
const vArray = range(1, 10, 2);
console.log(vArray); // [ 1, 3, 5, 7, 9 ]

ここで使っているのは、 Array.from() です。
新しく配列を生成したいときに使うことができます。

配列の値それぞれを加工する

5人の国語・数学・英語・理科・社会の5教科の合計得点を計算します。

const scores = [
    { '国語': 85, '数学': 78, '英語': 92, '理科': 62, '社会': 69 },
    { '国語': 23, '数学': 44, '英語': 78, '理科': 44, '社会': 50 },
    { '国語': 86, '数学': 10, '英語': 56, '理科': 82, '社会': 90 },
    { '国語': 31, '数学': 42, '英語': 96, '理科': 49, '社会': 68 },
    { '国語': 70, '数学': 55, '英語': 48, '理科': 89, '社会': 11 },
];

// for文
const vFor = [];
for(const score of scores) {
    vFor.push(score.国語 + score.数学 + score.英語 + score.理科 + score.社会);
}
console.log(vFor); // [ 386, 239, 324, 286, 273 ]


// Array
const vArray = scores.map((score) => {
    return score.国語 + score.数学 + score.英語 + score.理科 + score.社会;
});
console.log(vArray); // [ 386, 239, 324, 286, 273 ]

ここで使っているのは、 Array.prototype.map() です。
Array.prototype.forEach と異なり、与えられた配列の中身を順番に実行して、新しく配列を作成したい場合に、これを使うことができます。

配列の値をまたがって加工して1つの値を作成する

教科ごとの合計得点を計算します。

const scores = [
    { '国語': 85, '数学': 78, '英語': 92, '理科': 62, '社会': 69 },
    { '国語': 23, '数学': 44, '英語': 78, '理科': 44, '社会': 50 },
    { '国語': 86, '数学': 10, '英語': 56, '理科': 82, '社会': 90 },
    { '国語': 31, '数学': 42, '英語': 96, '理科': 49, '社会': 68 },
    { '国語': 70, '数学': 55, '英語': 48, '理科': 89, '社会': 11 },
];

// for文
const vFor = { '国語': 0, '数学': 0, '英語': 0, '理科': 0, '社会': 0 };
for(const score of scores) {
    vFor.国語 += score.国語;
    vFor.数学 += score.数学;
    vFor.英語 += score.英語;
    vFor.理科 += score.理科;
    vFor.社会 += score.社会;
}
console.log(vFor); // { '国語': 295, '数学': 229, '英語': 370, '理科': 326, '社会': 288 }


// Array
const vArray = scores.reduce((previous, score) => {
    return {
        '国語': previous.国語 + score.国語,
        '数学': previous.数学 + score.数学,
        '英語': previous.英語 + score.英語,
        '理科': previous.理科 + score.理科,
        '社会': previous.社会 + score.社会,
    };
}, { '国語': 0, '数学': 0, '英語': 0, '理科': 0, '社会': 0 });
console.log(vArray); // { '国語': 295, '数学': 229, '英語': 370, '理科': 326, '社会': 288 }

ここで使っているのは、 [Array.prototype.reduce()] です。(https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce) です。
与えられた配列の中身を順番に実行して、1つの値を作成したい場合に、これを使うことができます。

データを基に並列処理を行う

Yahoo! JapanGoogle へリクエスト送信を並列処理で行います。

import fetch from 'node-fetch';

const urls = [
    'https://www.yahoo.co.jp/',
    'https://www.google.com/',
];

// for文
(async () => {
    const promises = [];
    for(const url of urls) {
        promises.push((async () => {
            const response = await fetch(url);
            return await response.text();
        })());
    }
    console.log(await Promise.all(promises));
})();


// Array
(async () => {
    console.log(
        await Promise.all(
            urls.map(async (url) => {
                const response = await fetch(url);
                return await response.text();
            })
        )
    );
})();

リクエストの送信には、 node-fetchを使用しています。
Array側の方が階層は深くなってしまっていますが、書いている内容はシンプルです。
内容としては、 Array.prototype.map() を使って、 Promise が返る配列を作成し、それを Promise.all に渡しています。

(番外編)for...in

教科の一覧を表示します。

const score = { '国語': 86, '数学': 10, '英語': 56, '理科': 82, '社会': 90 };

// for文
for(const key in score) {
    console.log(key);
}


// Array
Object.keys(score).forEach((key) => {
    console.log(key);
});

for...in の書き換えには、 Object.keys() を併用します。
keyの一覧を配列として取得してからは、 Array.prototype.forEach() でも Array.prototype.map() でも Array.prototype.reduce() でも使用することができます。

おわりに

for文とArrayを使った書き方は、どちらがお好みでしょうか?
試しに作っているコードを、for文からArrayへ、Arrayからfor文へ書き直してみてください。

5
3
0

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
5
3