JavaScriptでプログラムを書いていると「配列・リストのそれぞれの要素に同じ計算を当てはめて変換する」処理を書きたくなることがありますよね(例えば、数字の配列のそれぞれの要素を2倍にしたい…など)。
そんなとき、初心者の方はfor文を駆使して処理を書くことが多いのではないでしょうか。
この記事ではfor文を使うよりも簡単に配列・リストの要素を変換できるmap関数について解説します!
この記事を読み終わる頃には配列・リストの要素変換に便利なmap関数を覚えて、for文を使った場合と比べてめちゃくちゃ簡潔な記述(頑張れば1行!)で変換ができるようになります。
Table of Contents(目次)
対象読者
JavaScriptの初心者で、「配列・リストのそれぞれの要素に同じ計算を当てはめて変換する」をfor文を使って書いている方に向けて書いています。
なお、本文中にラムダ式(() => console.log('Hello world!')
のような書き方)が出てきます。
この記事はラムダ式を知らない方でも読めるようになっていますが、ラムダ式を使った方が関数を短く簡潔に書けるようになりメリットが大きいです。
ラムダ式については以下の記事で初心者向けに解説しています。「ラムダ式わからないー!」という方は5分くらいで読めるのでよろしければ見てみてください。
for文を使って配列要素を変換する場合
map関数を使った場合と比較するためにまずはfor文を使って配列・リストの要素変換処理を書いてみます。
例として「数値の入っている配列・リストのそれぞれの要素を2倍にする処理」は以下のようになります。
let numList = [ 1, 2, 3 ]
// for文を使った場合
let resultList = []
for (let i=0; i<numList.length; i++) {
resultList.push(numList[i] * 2)
}
for文を使う場合、結果を保存するための配列を定義する必要があります(この例の場合はresultList)。
そして、for文を回しながら順番に各要素を取り出して、2をかけたものを新しく作った配列に追加しています。
map関数を使う場合
配列・リストの各要素を変換するのに便利な関数が”map”関数です。
配列.map(変換用関数)
とすると、配列の各要素を変換用関数で変換した結果を要素に持つ新しい配列を返します。
…と、言葉で説明するだけではイメージしづらいと思うので、早速例として「数値の入っている配列・リストのそれぞれの要素を2倍にする処理」を見てみましょう。
以下のコードを実行するとresultListに要素の値を2倍に変換した配列([2, 4, 6]
)が入ります。
let numList = [ 1, 2, 3 ]
// map関数を使った場合
let resultList = numList.map(function (e) {
return e * 2
})
では、このコードを順番に解説します。
まず、この例の中で変換用関数にあたるのは
function (e) {
return e * 2
}
という関数です。
これは、「引数eを受け取って2倍の値を返す」関数ですね!
map関数はこの変換用関数の引数eに配列の各要素を順番に入れて呼び出していき、返ってきた値を新しい配列に詰めて返してくれる関数なのです!
図にしてみると以下のようなイメージです。
また、for文を使った場合とは違い自分で結果用の配列を用意する必要がありません。map関数が新しい配列を用意して返してくれます。
for文の場合と比較するとコードが短くなっていますね。
let numList = [ 1, 2, 3 ]
// for文を使った場合
let resultList = []
for (let i=0; i<numList.length; i++) {
resultList.push(numList[i] * 2)
}
// map関数を使った場合
let resultList = numList.map(function (e) {
return e * 2
})
ちなみに、変換用関数の引数の名前は自分の好きに変えることができます。ここまでの例は配列の要素(=element)の頭文字eを引数の名前としていましたが、例えば「引数に渡されるのが数字だからnumにしよう!」というのもOKです。
// 引数の名前は自由
let resultList = numList.map(function (num) {
return num * 2
})
map関数を使った処理をもっと簡潔に書く方法
map関数はラムダ式と呼ばれる記法を使うとさらに簡潔に書くことができます。
let numList = [ 1, 2, 3 ]
// for文を使った場合
let resultList = []
for (let i=0; i<numList.length; i++) {
resultList.push(numList[i] * 2)
}
// map関数を使った場合
let resultList = numList.map(function (e) {
return e * 2
})
// map関数を使った場合(ラムダ式版)
let resultList = numList.map(e => e * 2)
ラムダ式を使うと矢印の左側の要素を右側に変換する、というように直感的に変換用関数を書くことができます。
説明すると長くなるので、この記事ではラムダ式については詳しく説明しません。ラムダ式について詳しく知りたい方は以下の記事で説明しているのでぜひ読んでみてください。
map関数を使って配列・リストから要素を抽出する例
他の例を見ながら使い方のイメージを固めましょう。
例1: 数値の符号を反転
let numList = [ 1, 2, 3 ]
// for文を使った場合
let resultList = []
for (let i=0; i<numList.length; i++) {
resultList.push(numList[i] * -1)
}
// map関数を使った場合(通常版)
let resultList = numList.map(function (e) {
return e * -1
})
// map関数を使った場合(ラムダ式版)
let resultList = numList.map(e => e * -1)
例2: 苗字のみに変換
以下の例では文字列を指定した文字で区切って配列にしてくれる関数splitを使って田中 太郎
を['田中', '太郎']
という配列にした上で1つ目の要素を取ることで苗字を取得しています。
let nameList = [
'田中 太郎',
'鈴木 一郎',
'山田 花子'
]
// for文を使った場合
let resultList = []
for (let i=0; i<nameList.length; i++) {
resultList.push(nameList[i].split(' ')[0])
}
// map関数を使った場合(通常版)
let resultList = nameList.map(function (name) {
return name.split(' ')[0]
})
// map関数を使った場合(ラムダ式版)
let result = nameList.map(name => name.split(' ')[0])
例3: ユーザオブジェクトの配列をユーザの年齢の配列に変換
let users = [
{ name: '太郎', age: 25 },
{ name: '花子', age: 27 },
{ name: '国子', age: 31 },
{ name: '里美', age: 21 }
]
// for文を使った場合
let resultList = []
for (let i=0; i<users.length; i++) {
resultList.push(users[i].age)
}
// map関数を使った場合(通常版)
let resultList = users.map(function (user) {
return user.age
})
// map関数を使った場合(ラムダ式版)
let result = users.map(user => user.age)
map関数で要素が何番目にあるかを変換に使いたい場合
ここまでで説明してきたように、map関数は配列.map(変換用関数)
という使い方です。
例えば、「map関数を使って偶数番目にある要素だけ2倍に変換したい」のように変換に要素の順番を使いたい場合、変換用関数の第2引数に要素番号が渡ってくるのでそれを使うことができます。
以下に偶数番目にある要素だけ2倍にする例を示します。引数に渡ってくる要素番号は0から始まる(0,1,2...
)ので偶数番目は要素番号を2で割った余りが1の場合です。
let numList = [ 1, 2, 3 ]
// for文を使った場合
let resultList = []
for (let i=0; i<numList.length; i++) {
resultList.push(i % 2 === 1 ? numList[i] * 2 : numList[i])
}
// map関数を使った場合(通常版)
let resultList = numList.map(function (e, i) {
return i % 2 === 1 ? numList[i] * 2 : numList[i]
})
// map関数を使った場合(ラムダ式版)
let resultList = numList.map((e, i) => i % 2 === 1 ? numList[i] * 2 : numList[i])
要素の順番を条件として使わない場合は第2引数は省略して書いてOKです。
また、第2引数の名前は自由に決めてOKです。今回は要素番号(=index)の頭文字iにしました。
map関数を繋げて複雑な変換を実現する
map関数は戻り値として配列を返すので、連続してmap関数を書くことができます。
このようにメソッドを複数並べて書くことをメソッドチェーンといいます。鎖のようにメソッドが連続して並んでるイメージです!
ひとつのmapで複雑な変換をするより、単純な変換をするmapを複数並べたほうが直感的で読みやすいコードになる場合があります。
例えば以下の例では、数値のリストを2倍したあとで4を足す変換をしています。
let numList = [ 1, 2, 3 ]
let result = numList.map(e => e * 2) // 2倍して
.map(e => e + 4) // 4を足す
おわりに
今回は配列・リストの要素を変換するmap関数の説明でした。
慣れてくるとむしろfor文で変換するのが気持ち悪いくらいの感覚になってくると思います。
ぜひ使いこなせるように練習してみてください。
また、今回紹介したmap関数と似たような使い方で、配列・リストの要素を絞り込むことができるfilter関数の解説記事も書いています。
両方マスターすることで要素の絞り込み・変換がめちゃくちゃ簡単に書けるようになるので興味があればそちらもご覧ください。