ADVERTISEMENT

【Googleスプレッドシート】Apps Scriptで配列をフィルターしてからmap!chainの基本

【Googleスプレッドシート】Apps Scriptで配列をフィルターしてからmap!chainの基本
🛡️ 超解決

Googleスプレッドシートで大量のデータを扱うとき、特定の条件に合う行だけを抽出してから別の処理をかけたい場面は多いです。例えば、売上データから一定額以上の取引だけを抜き出して、その金額に税率を掛けたい場合などです。Apps Scriptの配列メソッドfilterとmapを使えばこの処理を簡潔に書けますが、2つのメソッドを連続して呼び出す「チェーン」にすると、さらにコードが読みやすくなります。この記事では、filterとmapをチェーンする基本構文と、実際のスプレッドシート操作と組み合わせた実践的な使い方を解説します。

【要点】Apps Scriptのfilter→mapチェーンで配列を効率的に加工する

  • 配列のfilterメソッド: 条件に合う要素だけを抽出して新しい配列を返します。
  • 配列のmapメソッド: 各要素を変換して新しい配列を返します。
  • チェーン記法: array.filter(条件).map(変換) と続けて書くことで、中間変数を使わずに一連の処理を記述します。

ADVERTISEMENT

配列メソッドのチェーンとは何か

Apps Scriptの配列には、filter、map、reduceなどの便利なメソッドが用意されています。これらのメソッドは、元の配列を変更せずに新しい配列を返す特徴があります。そのため、戻り値に対してさらに別のメソッドを「.」(ドット)で連結して呼び出すことができます。これがチェーンです。

例えば、数値の配列から偶数だけを取り出し、それぞれを2倍にしたいとします。filterで偶数のみを抽出し、その結果に対してmapで2倍する、という処理を array.filter(n => n%2===0).map(n => n*2) のように1行で書けます。チェーンを使うと、中間結果を保存する変数が不要になり、コードが簡潔で読みやすくなります。

特にスプレッドシートのデータ処理では、getValuesで取得した二次元配列に対して、行全体を条件で絞り込み、さらに各行の特定の列だけを抜き出す、といった操作が頻繁に発生します。チェーンを使えば、そうした処理をスッキリと記述できます。

filter→mapのチェーンを実装する手順

準備:スプレッドシートからデータを取得する

  1. アクティブシートのデータを取得
    まず、対象の範囲をgetValuesで二次元配列として取得します。例えば var data = sheet.getDataRange().getValues(); です。
  2. データの構造を確認
    二次元配列は、各行が一つの配列で、列の値が並んでいます。例えば1行目がヘッダー、2行目以降がデータという構造が一般的です。

基本のチェーン:filterとmapを続けて書く

  1. filterで条件を指定する
    抽出したい条件をコールバック関数で記述します。例えば、B列(インデックス1)の値が100以上の場合だけ残すなら、data.filter(row => row[1] >= 100) と書きます。
  2. mapで変換を指定する
    抽出された各行に対して、必要な変換を適用します。例えば、A列(インデックス0)の値だけを取り出すなら .map(row => row[0]) と続けます。
  3. チェーン全体を変数に代入
    var result = data.filter(row => row[1] >= 100).map(row => row[0]); のように、チェーンの結果を変数に代入します。

実践例:売上データから高額取引の金額一覧を作る

シートに「日付」「金額」「商品名」の列があるとします。金額が5000円以上の取引の金額だけを抽出し、配列として取得します。

  1. データを取得
    var data = sheet.getDataRange().getValues(); で全てのデータを取得します。先頭行がヘッダーなら、data.shift(); でヘッダー行を除きます。
  2. filterで条件を設定
    data.filter(row => row[1] >= 5000) で金額の列(インデックス1)が5000以上の行だけに絞ります。
  3. mapで金額だけを抽出
    絞り込まれた各行から金額列だけを取得するため、.map(row => row[1]) と続けます。
  4. 結果をシートに書き出す
    var highAmounts = data.filter(row => row[1] >= 5000).map(row => row[1]); とし、sheet.getRange(1, 1, highAmounts.length, 1).setValues(highAmounts.map(v => [v])); で書き出します(二次元配列に変換)。

応用:複数の条件や複雑な変換

filterの条件を複数にしたり、mapで計算を加えたりすることも可能です。例えば、金額が5000以上かつ商品名が「りんご」の行を抽出し、金額に消費税(1.1倍)を掛けた値を取得するなら、 data.filter(row => row[1]>=5000 && row[2]==='りんご').map(row => Math.round(row[1]*1.1)) と書きます。

チェーンを使う際の注意点とよくある間違い

filterやmapのコールバック関数内でthisを使うと問題が起きる

アロー関数を使えばthisは外側のスコープを継承するため問題になりませんが、従来のfunctionを使うとthisの参照が変わることがあります。Apps Scriptでは基本的にアロー関数を使うことをおすすめします。

二次元配列の行全体を操作することを忘れない

getValuesで取得した配列は、各行が配列の配列です。filterやmapのコールバックの引数rowはその行の配列を指します。列のインデックスを間違えないように注意してください。

チェーンが長くなりすぎると可読性が落ちる

3つ以上のメソッドをチェーンすると、かえってコードが読みにくくなることがあります。その場合は適宜中間変数を使って分解するか、メソッドを複数行に分割して書くとよいです。Apps Scriptのエディタではセミコロンで行を区切るため、ドットの前で改行できます。

filterの条件に合致する要素がないと空配列になる

filterの結果が空配列の場合、その後のmapも空配列になります。その後の処理で空配列を想定していないとエラーになります。必要なら if (result.length === 0) { ... } で分岐してください。

setValuesで書き出すときは二次元配列に変換する

mapの結果は一次元配列になる場合が多いです。setValuesは二次元配列を要求するため、result.map(v => [v]) のように各行を配列で包む必要があります。

ADVERTISEMENT

filter→mapチェーンと別々に書いたコードの比較

記述方法 コード例 メリット
別々に記述 var filtered = data.filter(...);
var result = filtered.map(...);
中間結果を変数に保存するためデバッグしやすい
チェーンで記述 var result = data.filter(...).map(...); コード行数が減り、一連の処理が一目でわかる

まとめ

Apps Scriptのfilterメソッドとmapメソッドをチェーンすることで、スプレッドシートのデータ抽出と変換を簡潔に記述できるようになりました。この手法を使えば、中間変数を減らせるためコードの見通しが良くなります。実際にスクリプトを書くときは、まず小さなデータで動作確認をしながら徐々に複雑な条件に挑戦してみてください。次のステップとして、reduceメソッドのチェーンや、flatMapを使った応用も試してみるとよいでしょう。


ADVERTISEMENT

この記事の監修者
✍️

超解決 第一編集部

疑問解決ポータル「超解決」の編集チーム。正確な検証と、現場視点での伝わりやすい解説を心がけています。