これは何?
非エンジニア向けにGoogleAppsScript(GAS)レクチャーを行なっています。プログラムが全くの初めての人を対象にしています。このレクチャーを卒業し、基本的なことが理解できるようになった人が「その次に知っておいたほうがいいこと」の一つに 配列の扱い があるなと思いました。これを説明してみよう、という記事。
実務でよく使いそうな、filter
, map
, find
についてです。
対象者
-
GoogleAppsScriptおよびJavaScriptでの基本構文は知っている
-
具体的には ケーススタディでしっかり身につく! Google Apps Script超入門 を修了している
-
アロー関数について理解できている → まだの人は私がアロー関数を理解するまでを先に読んでおいてください!
[1] 配列の要素のうち特定の条件を満たすものだけを含む配列を作りたい (filter)
与えられた配列のうち、50以上の要素だけを抜き出したい(50以上の要素だけを持つ、新しい配列を生成したい)とします。
まずはこういう書き方になりそう
ケーススタディでしっかり身につく! Google Apps Script超入門に書かれている知識だけで処理しようとすると下記のようになります。
function filter1() {
// この配列の中から「50以上」の要素だけを取り出して新しい配列にしたい
const numbers = [80, 40, 80, 30, 60];
// 結果をいれるカラの配列を作って
const result = [];
// for文の中で条件に当てはまる要素を result に push する
for (const number of numbers) {
if (50 <= number) {
result.push(number);
}
}
// result は条件に当てはまるものだけが入った配列になる
console.log(result);
}
[ 80, 80, 60 ]
filterを使うとこうなる
function filter2() {
const numbers = [80, 40, 80, 30, 60];
const result = numbers.filter(number => 50 <= number);
console.log(result);
}
[ 80, 80, 60 ]
どうでしょうか。コード量がグっと減りましたね。
ただ、初めてこれを見たときに「...ん?」ってなりませんか?私はなりました。
numbers.filter(number => 50 <= number)
← ここね。
=>
は「アロー関数」という書き方になりますが、ここがわかってない人は 私がアロー関数を理解するまで を読んでほしい!
const result = numbers.filter(number => 50 <= number);
についてちょっと無理やり説明すると
numbers.filter(number =>
の部分で
-
numbers
配列に対してfilter
をかけるよ、っていうのがわかる -
numbers
配列から順番に1つずつ要素を取り出して(←ここにループの要素が含まれている)number
という変数に代入するよ
という理解をしています。
さらに、「フィルタリングする条件」は何かというと
50 <= number
であり、この条件を満たした要素をresult
配列に入れていく(result
にpush
)
その結果として「フィルタリングの条件を満たす要素だけが入ったresult
配列が生成される」になります。
const result = numbers.filter(number => 50 <= number);
仕様として
-
filter
の戻り値は「配列」です - この例だと
result
は[ 80, 80, 60 ]
という配列になります - フィルタリングの条件を満たす要素が1つもない場合は、空の配列
[]
になります - 元の配列(
numbers
)は変更されません
詳細について知りたい人はこちら→ Array.prototype.filter()
[2] 配列の要素全てに対して何かの処理をして、新たな配列を作りたい (map)
例えば5人に100点満点のテストを受けてもらって、その結果があったとして、何らかの理由で「全員に+10点する」みたいな処理をしたいとします。
まずはforで書くよね
function mapFunc1() {
const scores = [80, 40, 80, 30, 60];
// 結果をいれるカラの配列を作っておいて、
const result = [];
// ループさせて各要素に対して+10の処理をして、result に push
for(const score of scores){
result.push(score+10);
}
// 結果として各要素が+10された配列ができあがる
console.log(result);
}
[ 90, 50, 90, 40, 70 ]
mapを使うとこうなる
function mapFunc2() {
const scores = [80, 40, 80, 30, 60];
const result = scores.map(score => score + 10);
console.log(result); // [ 90, 50, 90, 40, 70 ]
}
const result = scores.map(score => score + 10);
についての理解として
-
scores
配列に対してmap
の処理をするよ -
scores
配列から1つ取り出した要素をscore
変数にいれるよ -
score + 10
した結果をresult
に入れていく (result
にpush
) よ
map
は配列の「全て」の要素に対して、同じ処理をしたいときに使えます。
仕様として
-
map
の戻り値は配列です - 元の配列(
scores
)は変更されません
詳細について知りたい人はこちら→ Array.prototype.map() - JavaScript | MDN
mapの実践編
せっかくなので実務で使いそうなケースを考えてみます。
スプレッドシートでこんなデータがあるとします。
全ての人に対して「姓+名」の文字列を生成したい、みたいなケースってありそうですよね。
function mapFunc3() {
// スプレッドシートから取得したデータは2次元配列になっている
const data = [
['田中', '太郎'],
['山本', '花子'],
['鈴木', '一郎'],
['高橋', '由美'],
['佐藤', '健太'],
['伊藤', '美咲'],
['渡辺', '大輔'],
['中村', '結衣'],
['小林', '拓海'],
['加藤', '杏奈']
];
const result = data.map(row => row[0] + row[1]); // 文字列連結の'+'
console.log(result);
}
['田中太郎', '山本花子', '鈴木一郎', '高橋由美', '佐藤健太', '伊藤美咲', '渡辺大輔', '中村結', '小林拓海', '加藤杏奈']
どうでしょう?コードの中身は理解できますか?
今回はdata
が二次元配列なので
data.map(row => row[0] + row[1])
は「data
から1つの要素を取り出してrow
変数にいれる」わけですが、このときのrow
は [姓, 名]
という配列です。
[3] 配列の要素のうち、条件を満たす要素を1つ取り出す (find)
filter
と似ていますが「条件を満たす要素があったらその要素を取り出す」という処理です。
例えばあるクラスでテストを実施して、「名前」と「点数」のリストが存在する。
この中から特定の名前の人の情報を探したい。みたいな。
まずはこういう書き方になるかな。
function findFunc1() {
const data = [
{ name: '田中太郎', score: 80 },
{ name: '山本花子', score: 40 },
{ name: '鈴木一郎', score: 80 },
{ name: '高橋由美', score: 30 },
{ name: '佐藤健太', score: 60 }
];
const targetName = "鈴木一郎"; // この名前の人の情報を探したい
// 結果を入れる変数
let result;
// forを回して一致する要素があれば result に入れて break する
for(const member of data){
if(member.name === targetName){
result = member;
break;
}
}
console.log(result);
}
{ name: '鈴木一郎', score: 80 }
findを使って書いてみる
function findFunc2() {
const data = [
{ name: '田中太郎', score: 80 },
{ name: '山本花子', score: 40 },
{ name: '鈴木一郎', score: 80 },
{ name: '高橋由美', score: 30 },
{ name: '佐藤健太', score: 60 }
];
const targetName = "鈴木一郎"; // この名前の人の情報を探したい
const result = data.find(member => member.name === targetName);
console.log(result); // { name: '鈴木一郎', score: 80 }
}
const result = data.find(member => member.name === targetName);
-
data
に対してfind
を実行するよ -
data
から1つ取り出してmember
変数にいれるよ -
member.name === targetName
を満たす要素があったらresult
に代入するよ
という意味です。
仕様として
- 条件を満たす要素が存在しない場合は
undefind
を返します - 条件を満たす要素が複数ある場合、条件を満たす最初の要素を返します
になります。filter
は条件を満たす要素すべてを配列として返しますが、find
は「最初に見つかった要素だけ」を返します。
詳細について知りたい人はこちら→Array.prototype.find() - JavaScript | MDN
おわりに
JavaScript、GASでは「配列を扱う便利な関数」がいっぱいあります。
Array - JavaScript | MDNで調べてみてください。
今回紹介した3つ以外では concat
, every
, flat
, includes
, join
, some
などがよく使いそうでしょうか。
配列を操作するときには「自分で処理を考えるより先に、それをやってくれる関数を探す」のがいいと思います!