LoginSignup
0
0

More than 1 year has passed since last update.

ノンプロ研 GAS初級講座21期 補講 #2-3

Last updated at Posted at 2023-01-31

概要

ノンプログラマーのためのスキルアップ研究会 GoogleAppsScript初級講座
第2回「制御構文」
第3回「関数・配列」
についての非公式の補講記事です。
21期講師のTaitoが執筆しています。

2回分をまとめてみたら、とても長い分量になってしまいました。反省しています!
ざっと眺めていただいて、気になったところは直接ご質問くださいませ。

第2回 制御構文

ここだけ覚えるポイント

  • プログラムの実行順制御する書き方
  • 条件式(true false)で判定する
    • ずーみんTAの言う「条件式は門番のようなもの」がわかりやすいです!
    • 論理演算子で拡張
      • && かつ
      • || または
  • 選択処理 - if文 switch文
    • 分岐
    • 上から順に条件式を評価、最初にマッチしたブロックを実行
  • 反復処理 - for文 while文
    • 繰り返し
    • ループ毎に条件式を評価、falseなら終了
  • if文for文が書ければOK

条件式について(補足)

条件式は変数に入れられます。
うまく使うと、コードの可読性が上がります。

const fizz = i % 3 === 0;
const buzz = i % 5 === 0;
if(fizz && buzz) {
  console.log('FizzBuzz'); // iが3と5で割り切れる時に実行
} 

条件式は暗黙の型変換をするので、
trueに変換される(truthy)値、falseに変換される(falsy)値も利用できます、
が、一見して分かりづらいコードになることが多いので、乱用は厳禁です。

// iは1以上でtrue、0でfalseに変換され、ループを停止します
for(let i = 3; i; i--) {
  console.log(i);
} // 3, 2, 1

for(let i = 3; i > 0; i--) { // 素直に書いたほうが何をしてるかわかりやすい
  console.log(i);
} // 3, 2, 1

(もっと発展)===厳密等価と==等価の違い

条件式を==で書くと暗黙の型変換をされてしまい、不都合が多いです。
まったく違うデータである筈の以下の条件式がtrueになってしまいます。

1 == [1]; // true
0 == ''; // true
[[]] == false; // true

対照表はこんな感じです。
覚える必要はありません。ちゃんと===を使えばOKです!


選択処理

if文

if(条件式A) {
  // 条件式Aがtrueなら実行
} else if(条件式B) {
  // 条件式Bがtrueなら実行
} else {
  // その他の場合実行
}

switch文

switch() {
  case 値A:
    // 式 === 値Aがtrueなら実行
    break;
  case 値B:
    // 式 === 値Bがtrueなら実行
    break;
  default:
    // いずれにもあてはまらなければ実行(省略可)
}

/** こうも書けます */
switch(true) {
  case 条件式A:
    // true === 条件式A つまり条件式Aがtrueなら実行
}

(ちょっと発展)ifとswitchの使い分け

条件分岐はif文で書くのが一般的ですが、場合によってはswitchを優先することもあります。

  • 分岐がシンプルで、且つ多岐にわたる時
  • 複数の条件に同じ処理を入れたい時
    • breakを省略したフォールスルーという書き方があります
    • 実践で使うことはほぼありません
const rank = '';
switch (rank) {
  case '':
    console.log('成績上位者です!');
    // breakを省略すると、breakが出てくるまで実行を続ける
  case '':
  case '':
    console.log('合格です');
    break;
  case '不可':
    console.log('不合格です');
    break;
}

反復処理

for文

for(初期化式; 条件式; 増減式) {
  // 処理
}
/**
 *  初期化式→条件式→処理→増減式
 *         →条件式→処理→増減式... と繰り返します
 *  条件式がfalseになると終了
 */

while文

初期化式;
while(条件式) { // 条件式がfalseになると終了
  // 処理
  増減式;
}

条件式が最終的にfalseになるように、
増減式で変化する値を、条件式に組み込んであげる必要があります。

(ちょっと発展)forとwhileの使い分け

  • ループ毎に増減式を実行して、次のループにうつる
  • 条件式で終了判定をする

という構造は同じです。なので、互いに同じことができます。
どちらでもよければ、for文で書くのが一般的かな?と思います。
求めている処理に対して見やすい書き方を選びましょう。


/** for文はループ設定が1箇所にまとまってて見やすい */
for(let index = 0; index < array.length; index++) {
  // 配列の最初から最後までループする処理
}

/** while文はループ回数が決まっていない時に見やすい */
while(files.hasNext()) { // filesオブジェクトが次のファイルを持っている限り続ける
  file = files.next(); // 次のファイルを取り出す(増減式)
  // 処理
}

/** 構造を理解すれば、while文みたいなfor文も書けます */
let i = 1; // 初期化式
for( ;i <= 3; ) { // 条件式 ()内はどの式も省略可
  console.log(i);
  i++; // 増減式
} // 1, 2, 3

(もっと発展)breakとcontinue

ループ処理はbreakとcontinueで処理を止めることができます。

  • break ループ全体を終了する
  • continue そのループの処理のみ終了し、次のループに移る

VLOOKUP関数などと同じで、1つ値が見つかったらそこで処理を止める、みたいな感じです。
要所要所でよく使うので、憶えておきましょう!

  for (let i = 1; i <= 5; i++) {
    if (i === 3) continue; // 3はスキップ
    console.log(i);
  } // 1, 2, 4, 5

  let j = 1;
  while (j <= 5) {
    if (j === 3) break; // 3で終了
    console.log(j);
    j++;
  } // 1, 2

  /** NOTE: if文は処理が1行であれば{}を省略できます */

(もっともっと発展)様々な省略記法(ショートハンド)

  • if文の省略記法 3項演算子
  • 暗黙の型変換
  • for文の構造理解

こういった発展要素を全部盛りすると、
宿題のFizzBuzz問題はこんな風にも書けます。

for(let i=1;i<=15;console.log(!(i%15)?'FizzBuzz':!(i%3)?'Fizz':!(i%5)?'Buzz':i),i++);

初めて見た時は何じゃこりゃー、と思いました。
これが書けるようになる必要はまったくありません
こういうコードの書き方をするのは人に伝わりづらいので非推奨ですが
知識として入れておくと、何かの際に役に立つこともあるかもしれません。

第3回 関数・配列

ここだけ覚えるポイント

  • 関数
    • プログラムの実行単位
    • 引数を受け取って戻り値を返すもの←NEW!
    • 関数リテラル、アロー関数の話は一旦忘れましょう
  • 配列
    • たくさんのデータをまとめておける連続した箱
    • インデックス(0始まりの番号)を使ってアクセスする
  • 関数も配列も入れ子にできる

関数

第2回まで関数はただの実行単位でしたが、
実は引数を受け取って、戻り値を返すという非常に重要な機能を持っています。

/**
 * 1からnumまでを足した数を返す関数(こういうコメントがあると親切)
 * @param {number} num - 仮引数: 1からこの数まで足し合わせる
 * @return {number} sum - 戻り値: 合計値
 */
function getSum(num) {
  let sum = 0;
  for (i = 1; i <= num; i++) {
    sum += i;
  }
  return sum;
}

function myFunction3_02_02() {
  getSum(10); // ←1から10までを足した数 55 が戻ってきている

  // returnだけだとログ出力されないので、戻り値を確認する時はconsole.log()
  console.log(getSum(10)); // 55
}

この「引数と戻り値」の機能を使って、実に様々なことが出来るようになります。
楽しみにお待ちください!

(ちょっと発展)コード関数とシート関数

引数と戻り値の話は、Excelやスプレッドシートの関数を思い出すと腹落ちしやすいです。
image.png
シート関数は、引数となるセルが変わると、別の結果を返します。
引数が違うと、同じ処理を使って、違った結果を返せるのが関数の強みです。

関数を書くこと === この処理を書くことです。
たとえば上のシート関数をコードで表現するとしたら、こうなります。

function multiply(x, y) {
  return x * y;
}

function sum(numbers) {
  let result = 0;
  // 範囲を1次元配列にしてfor文で足し合わせます
  for(const number of numbers.flat()) {
    result += number;
  }
  return result;
}

なお、エディタに書いた関数はスプレッドシートから呼び出すこともできます。
こちらは講座第7回で紹介します。


配列

配列も、スプレッドシートと紐づけて考えるとわかりやすいです。
たとえばシートのこういう表は
image.png
2次元配列にするとこうなります。

[ [ '名前', '年齢', '性別' ],
  [ 'Alice', 20, '女性' ],
  [ 'Bob', 30, '男性' ],
  [ 'Charlie', 40, '男性' ] ]

1行ごとが1次元配列で、全体が2次元配列になっていますね。
'Bob'にアクセスしたい時は、[インデックス]で指定します。
インデックスは0から始まるので、行列番号とは1ズレています。注意しましょう。

const values = [
  [ '名前', '年齢', '性別' ],
  [ 'Alice', 20, '女性' ],
  [ 'Bob', 30, '男性' ],
  [ 'Charlie', 40, '男性' ]
  ];
console.log(values[2][0]); // Bob 3行目1列目(インデックス2,0)

for of文

急に出てきました、新しいfor文の書き方です。
超便利です。

for(const record of values) {
  console.log(record);
}
// 以下順に出力されます
//  record -> [ '名前', '年齢', '性別' ]
//  record -> [ 'Alice', 20, '女性' ],
//  record -> [ 'Bob', 30, '男性' ],
//  record -> [ 'Charlie', 40, '男性' ]

for of文はイテラブル(反復可能)なデータに対して、
最初から最後までの要素を順にループする為の構文です。
for文のこの形が省略されているイメージです。

for (let i = 0; i < values.length; i++) {
  const record = values[i];
  console.log(record);
}

for of文の書き方がわからない!という時は
一度通常のfor文で書いてみると、理解しやすいですよ!


2回分をまとめると、分量が大変なことになってしまいました…。
次回更新は2/7(火)の予定です。
引き続きよろしくお願いします!

参考書籍

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0