2021/1 for文を使うその前に

佐々木誠
大阪

繰り返し・ループ処理map, filter, find, some, reduceについて紹介します。 プログラミング言語によっては備えていませんが、利便性から類似機能のライブラリが存在したりします。

繰り返し処理

for文でのループ処理は、プログラミングの最初に学ぶ基本となる構文です。 そのため繰り返し処理を行いたい時には、自然とfor文を使う人も多いと思います。

溢れ出すバグ

しかし、無意識に使っているfor文を、map, filter, find, some, reduceなどに置き換えるとロジックが明確になりバグは減り、可読性・メンテナンス性も向上することでしょう。

何が良いのか?

何が良いのか説明するために、まずmapfilterについて紹介します。

map

const prices = [100, 150, 500];
const withTaxes = prices.map((price)=>{
    return price * 1.1;
});
// [110, 165, 550]

prcies配列から消費税込の価格withTaxes配列を生成したように、 map関数は新しい配列を生成する関数です。

filter

const prices = [1000, 15000, 30000];
const highItems = prices.filter((price)=>{
    return price >= 10000;
});
// [15000, 30000]

prcies配列から1万円以上の高級品を抽出しhighItems配列を生成しました。 filter関数は条件に一致したデータだけを抽出した新しい配列を生成する関数です。

for文でできる

もちろん、これらはfor文で生成することもできます。 ではfor文と比べて何が良いのか?というと2つあります。

可読性

1つは読み返したり、他の人が読んだときの処理の意図の伝わりやすさです。

良いこと

for文は自由度が高いために、for文では新しい配列を作りたいのか?抽出をしたいのか? コードを目を皿にして良く読まなければわかりません。

しかし、map filterはデータをどう加工したいのか、何をしたいかが明白なため読み手は迷うことはありません。

副作用

もう1つは、mapやfilterは必ず新しい配列データを生成し、元のデータは何も変わらないところにあります。

for文でももちろんできますが、元の変数(データ)を上書きすることもできるため実装者によってばらつきが出ます。 特に初学者は、別の変数名を考えることが億劫なため元データを上書きすることは良くあります。

目眩

そして元のデータを上書きすることは、同じ変数名なのに役割が途中で変わってしまいます。 一度出来上がったコードの途中に、このような処理を入れてしまうと後続の処理にも影響が出てしまいます。

後続の処理は、期待したデータではない場合もありますし、上書き前のデータを活用したくてもできなくなってしまいます。

生産性

新規にコードを起こす時点では問題になりませんが、半年後・一年後に他の人が改修する際に可読性と副作用が生産性に影響してしまいます。

てこの原理

もちろん、理由があってfor文を利用することは問題ありません。パフォーマンスの観点から使うケースもあるでしょう。しかし、特段理由がなければ、for文ではなくmapやfilter、以降で紹介するものを利用すると良いでしょう。

mapを使うかfilterを使うか選ぶ中で、処理も頭の中も自然と整理され、動作確認すべきパターンも整理され、結果的にバグも出にくくなります。

find

const users = ['sato', 'takahashi', 'tanaka'];
const target = users.find((user)=>{
    return user == 'tanaka';
});
// 'tanaka'

users配列から特定のユーザーを見つけ出しました。 find関数は配列から条件にあったデータを見つけ出す関数です。

some

const data = ['jp', 'us', 'cn', 'fr'];
const isNext = data.some((item)=>{
    return item == 'ch' || item == 'kr';
});
// true

data配列に、日本の隣国が含まれたデータかどうか判定しました。 some関数は配列が条件にあったデータかどうかテストする関数で、戻り値はブールになります。

reduce

const data = [1, 2, 3, 4, 5];
const sum = data.reduce((prev, current)=>{
    return prev + current;
});
// 25

const max = data.reduce((prev, current)=>{
    return prev < current ? current : prev;
});
// 5

const min = data.reduce((prev, current)=>{
    return prev < current ? prev : current;
});
// 1

今までの関数よりわかりにくく、説明が長くなるので今回は割愛します。 利用シーンとしてはこのように集計をする際に役立ちます。 興味の湧いた方は、是非調べて理解を深めてください。

最後に

some, reduceは利用頻度は少ないですが、無意識に実装していた繰り返し処理にも種類があることに気付いていただけたと思います。処理が明確になることはとても良いことですので、是非活用してみてください。

こんな記事も読まれています