[GAS]オブジェクトにフィルターをかけて抽出しよう 反復メソッドによる抽出 Day2

obj2EffectiveGoogleAppsScript

どうも。つじけ(tsujikenzo)です。このシリーズでは「オブジェクトにフィルターをかけて抽出しよう」をお届けします。全3回でお送りします。今日は2回目です。

この記事は、#Effective GoogleAppsScriptタグがついております。

前回のおさらい

前回は、「はじめに」ということで、オブジェクト化レコーズとfor in文をお届けしました。

今回は、「反復メソッドによる抽出」をお届けします。

今日のアジェンダ

  • 反復メソッドを用いた値による抽出
  • 反復メソッドを用いたプロパティによる抽出
  • オブジェクト化レコーズのプロパティの抽出

反復メソッドを用いた値による抽出

配列の反復メソッドの1つであるforEach()メソッドは、配列の各要素に処理を行います。

forEach()メソッド内部では、配列のインデックスを使って、外部の配列を順番に呼び出せます

また、forEach()メソッド内部を改行し、複数の処理を行うこともできます。

const tag = ["A", "B", "C"];
const numbers = [1, 2, 3];
numbers.forEach((number, index) => {
  console.log(`${tag[index]} - ${number}`);
  console.log();
});

//A - 1
//
//B - 2
//
//C - 3

このテクニックを応用し、オブジェクトの特定の値に該当するプロパティのみを抽出する、という処理ができます。

「抽出する」とは、「新しい空のオブジェクトを作成して、必要な要素を格納していく」というのもポイントです。元のオブジェクトを改変するのではありません。

const member = { id: 1, name: "Tsujike", address: "Hokkaido" };
const keys = Object.keys(member);
const values = Object.values(member);

const newObj = {};
keys.forEach((key, index) => {
  if (values[index] === "Tsujike") newObj[key] = values[index];
});

console.log(newObj);//{ name: 'Tsujike' }

if文の条件式は、「オブジェクトの特定の値が含まれないプロパティ」も可能です。

const newObj2 = {};
keys.forEach((key, index) => {
  if (values[index] !== "Tsujike") newObj2[key] = values[index];
});
console.log(newObj2); //{ id: 1, address: 'Hokkaido' }

※2023年1月追記

プロパティを指定して抽出する方法その2

オブジェクトを配列に変換してforEach()メソッド、というアプローチのほかに、Object.entries()Object.fromEntries()というObjectクラスのStaticメソッドで抽出する方法があります。

const member = { id: 1, name: "Tsujike", address: "Hokkaido" };

//指定したプロパティで抽出する
const filterdObject = Object.entries(member).filter(([key]) => key === 'name' || key === 'id');

//配列をオブジェクトに変換する
const newObj = Object.fromEntries(filterdObject);

console.log(newObj); //{ id: 1, name: 'Tsujike' }

削除するプロパティを指定する

削除するプロパティが少ないときは、delete演算子の方がラクなばあいもあるでしょう。

const member = { id: 1, name: "Tsujike", address: "Hokkaido" };

//削除するプロパティを指定する
delete member.address;

console.log(member); //{ id: 1, name: 'Tsujike' }

反復メソッドを用いたプロパティによる抽出

さきほどは、オブジェクトの値でしたが、今回は、オブジェクトのプロパティを条件式にします。

オブジェクトの特定のプロパティに該当するプロパティのみ、抽出してみましょう。

const member = { id: 1, name: "Tsujike", address: "Hokkaido" };
const keys = Object.keys(member);
const values = Object.values(member);

//idプロパティとnameプロパティのみ抽出
const newObj = {};
keys.forEach((key, index) => {
  if (key === "name") newObj[key] = values[index];
  if (key === "id") newObj[key] = values[index];
});
console.log(newObj); //{ id: 1, name: 'Tsujike' }

これは、このように短絡演算(ショートハンドともいいます)で書き換えることができます。

どちらが可読性が高いかは、ときとばあいによります。(値の列挙は、縦に伸びた方が読みやすいこともあります)

keys.forEach((key, index) => {
  if (key === "name" || key === "id") newObj[key] = values[index];
});

同様に、オブジェクトの特定のプロパティに該当しないプロパティのみ、抽出してみましょう。

const newObj2 = {};
keys.forEach((key, index) => {
  if (key !== "name") newObj2[key] = values[index];
});
console.log(newObj2); //{ id: 1, address: 'Hokkaido' }

該当しないプロパティが複数あるばいは、このように記述します。

const newObj3 = {};
keys.forEach((key, index) => {
  if (key === "name") return;
  if (key === "id") return;
  newObj3[key] = values[index];
});
console.log(newObj3); //{ address: 'Hokkaido' }

短絡演算でも、記述してみましょう。

const newObj4 = {};
keys.forEach((key, index) => {
  if (key === "name" || key === "id") return;
  newObj4[key] = values[index];
});
console.log(newObj4); //{ address: 'Hokkaido' }

さまざまな抽出条件の入れ替え

とあるオブジェクトから、必要なプロパティを抽出するとき、以下はおなじ結果を出力します。

  • 必要なプロパティをすべて指定する
  • 不要なプロパティをすべて指定して否定する

これは、「必要なプロパティがいくつあるのか」によって、最適な処理が異なります。

「かならずこう書けば最適な処理である」という正解がない、プログラミングのむずかしいポイントだと思います。

条件分岐の真偽の入れ替えは、「ド・モルガンの法則」が有名です。ぜひ、学習してみましょう。

オブジェクト化レコーズのプロパティの抽出

いよいよ本題にはいります。

処理順を考えよう

本題にはいるまえに、処理を切り分けて設計していきましょう。

データベースは、データが増えるたびに、下に向かって縦に伸びる原則があります。

なので、先に見出し行を抽出したほうが、そのあとの処理が早いです。 

正解はありませんが、この順で設計していいと思います。 

プロパティの抽出

前回の復習です。プロパティはこのように抽出しました。

const member = { id: 1, name: "Tsujike", address: "Hokkaido" };
const keys = Object.keys(member);
const values = Object.values(member);
const newObj = {};
keys.forEach((key, index) => {
  if (key === "name" || key === "id") newObj[key] = values[index];
});
console.log(newObj);

オブジェクト化レコーズの抽出

forEach()メソッド同様に、配列の各要素を処理して、新しい配列を生成するのが、map()メソッドです。

const tag = ["A", "B", "C"];
const numbers = [1, 2, 3];
const mappedNumbers = numbers.map((number, index) => {
  return [`${tag[index]} - ${number}`];
});

console.log(mappedNumbers); 
//[ [ 'A - 1' ], [ 'B - 2' ], [ 'C - 3' ] ]

オブジェクト化レコーズの配列に、map()メソッドをぶつけて、内部にプロパティ抽出処理を記述すればOKです。

//オブジェクト化レコーズ
const members = [
  { id: "tg001", name: "Tsujike", address: "Hokkaido" },
  { id: "tg002", name: "Takahashi", address: "Fukuoka" },
  { id: "tg003", name: "Etau", address: "Tokyo" },
];

//必要なプロパティのみ抽出
const filteredProperties = members.map(member => {

  const keys = Object.keys(member);
  const values = Object.values(member);
  const newObj = {};
  keys.forEach((key, index) => {
    if (key === "name" || key === "id") newObj[key] = values[index];
  });

  return newObj;
});

console.log(filteredProperties);
//[ { id: 'tg001', name: 'Tsujike' },
// { id: 'tg002', name: 'Takahashi' },
// { id: 'tg003', name: 'Etau' } ]

次回は、応用編です。

まとめ

以上で、「反復メソッドによる抽出」をお届けしました。

配列の反復メソッドを習得すると、ソースコードからfor文を減らし、可読性を高めることができます。

理解が進むにつれて、パズルを解くように、病みつきになりますよ。

次回は、最終回で「配列による反復と抽出」をお届けします。

GitHubリポジトリ

GitHub - tsujike/-Blog-ObjectFilter: [オブジェクトにフィルターをかけて抽出しよう
[オブジェクトにフィルターをかけて抽出しよう. Contribute to tsujike/-Blog-ObjectFilter development by creating an account on GitHub.

このシリーズの目次

タイトルとURLをコピーしました