概要
ノンプログラマーのためのスキルアップ研究会 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を省略した
フォールスルー
という書き方があります - 実践で使うことはほぼありません
- 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やスプレッドシートの関数を思い出すと腹落ちしやすいです。
シート関数は、引数となるセルが変わると、別の結果を返します。
引数が違うと、同じ処理
を使って、違った結果を返せるのが関数の強みです。
関数を書くこと === この処理
を書くことです。
たとえば上のシート関数をコードで表現するとしたら、こうなります。
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回で紹介します。
配列
配列も、スプレッドシートと紐づけて考えるとわかりやすいです。
たとえばシートのこういう表は
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(火)の予定です。
引き続きよろしくお願いします!
参考書籍