どうも。つじけ(tsujikenzo)です。このシリーズでは「オブジェクトにフィルターをかけて抽出しよう」をお届けします。全3回でお送りします。
この記事は、#Effective GoogleAppsScriptタグがついております。
今日のアジェンダ
- 達成したいゴール
- テーブルのオブジェクト化
- オブジェクトとfor in文
達成したいゴール
スプレッドシートをデータベースとして扱うときは、主キー(primary key) と 見出し行(header) をもつ 「テーブル構造」 が基本です。
とあるテーブルから、必要な値のみを抽出するばあい、みなさんはどのような処理を行いますか?
セルにQUERY関数などの式を挿入するのも、1つの手段だと思います。(こちらのnoteをオススメします。) https://note.com/kawamura_/n/n38726f528643
これを、GASで操作してみましょう。
オブジェクト化レコーズ
テーブル構造のデータを取得・加工するさい、「列の追加や、列の移動されたらGASが壊れる」という心配があります。
なので、テーブルの見出し行と値がセットになった、オブジェクトに変換して処理を行います。
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("シート1");
const [header, ...records] = sheet.getDataRange().getValues();
const objectRecords = records.map(record => {
const obj = {};
header.forEach((element, index) => obj[element] = record[index]);
return obj;
});
console.log(objectRecords);
// [ { id: 'tg001', name: 'Tsujike', address: 'Hokkaido' },
// { id: 'tg002', name: 'Takahashi', address: 'Fukuoka' },
// { id: 'tg003', name: 'Etau', address: 'Tokyo' } ]
このような形式を、「オブジェクト化レコーズ」 と呼ぶことにします。
オブジェクトに変換することで、今まで配列のインデックスで指定していた見出し行を、具体的な値(idやnameなど)で指定できます。
列が移動したり、列の増減があっても、GASが壊れることはありません。
//配列のインデックスで指定
console.log(records[0][0]); //tg001
console.log(records[2][2]); //Tokyo
//オブジェクト化
console.log(objectRecords[0]["id"]); //tg001
console.log(objectRecords[2]["address"]); //Tokyo
さまざまな加工処理を行ったあとは、再び2次元配列に戻して、スプレッドシートに貼り付けたりします。
const undoObjectRecords = objectRecords.map(record => Object.values(record));
console.log(undoObjectRecords);
// [ [ 'tg001', 'Tsujike', 'Hokkaido' ],
// [ 'tg002', 'Takahashi', 'Fukuoka' ],
// [ 'tg003', 'Etau', 'Tokyo' ] ]
ぜひ、スニペット化しましょう。
オブジェクトとfor in文
for in文は、オブジェクトのプロパティを捜査するループ処理です。
しかし、見かけの順序通りの取り出しが補償されていなかったり、プロトタイプチェーンを遡ったり、バグを生む原因になることもあります。
const member = { id: 1, name: "Tsujike", address: "Hokkaido" };
member.__proto__.property = "";
console.log(member); //{ id: 1, name: 'Tsujike', address: 'Hokkaido' }
for (const value in member) {
console.log(value); //id, name, address, property
}
このため、多くのプログラマは、for/inループではなく、Object.keys()を使ってfor/ofループを利用するようになっています。(脚注1)
Objectクラスの便利なメソッドたち
GASのObjectクラスでは、オブジェクトのプロパティ(GASではkeyと呼んでいます)や値を取得するメソッドが、3つ提供されています。
実際に、コードで確認してみましょう。
const member = { id: 1, name: "Tsujike", address: "Hokkaido" };
const keys = Object.keys(member);
console.log(keys); //[ 'id', 'name', 'address' ]
const values = Object.values(member);
console.log(values); //[ 1, 'Tsujike', 'Hokkaido' ]
const element = Object.entries(member);
console.log(element); //[ [ 'id', 1 ], [ 'name', 'Tsujike' ], [ 'address', 'Hokkaido' ] ]
for (const [key, value] ofObject.entries(member)) {
console.log(`key:${key} と value:${value}`);
}
//key:id と value:1
//key:name と value:Tsujike
//key:address と value:Hokkaido
戻り値はすべて配列というのが、ポイントです。
次回は、この配列を、反復処理しましょう。
まとめ
以上で、「オブジェクトにフィルターをかけて抽出しよう」の「はじめに」をお届けしました。
オブジェクト化レコーズとObjectクラスの3つのメソッドを、ぜひ覚えましょう。
次回は、「反復メソッドによる抽出」をお届けします。
参考文献
- 脚注1 引用元:JavaScript 第7版 O’Reilly Japan