フォルトンに複雑な計算式をわかりやすくしてもらいましょう。
下記の問題について、とりあえず作った計算式の変数名を変更して、解説を行ってもらいました。
フォルトンは、変数名の変更とコメントを追加してくれました。
- 問題のトピック
- フォルトンの最適化
スレッドの内容
下記の2テーブルからテーブルデータを組み立てる式の変数名を6文字以内で妥当にものに。
LET(
a,JSON_P(OTVAL(見積枚数)),
b,JSON_P(OTVAL(使用材料)),
tbl, ARRAY(),
dmy, ARRAY_MAP(a,xx,
ARRAY_MAP(b,yy,
FSET(tbl, ARRAY(tbl,
DIC(
"枚数",DIC_ITEM(xx,"枚数"),
"材料名",DIC_ITEM(yy,"材料名")
)
))
)
),
tbl
)
rex0220 計算式プラグインの使い方 の発言:
思考時間: 19s
いいですね。6文字以内で“中身が分かる”名前に直した版です![]()
LET(
maisu, JSON_P(OTVAL(見積枚数)), // 見積枚数テーブル → 配列
zairyo, JSON_P(OTVAL(使用材料)), // 使用材料テーブル → 配列
rows, ARRAY(), // 出力用の配列バッファ
wk, ARRAY_MAP(maisu,m, // ダミー(副作用で rows を積む)
ARRAY_MAP(zairyo,z,
FSET(rows, ARRAY(rows,
DIC(
"枚数T", DIC_ITEM(m,"枚数"),
"材料名T", DIC_ITEM(z,"材料名")
)
))
)
),
TABLE_DATA(rows)
)
maisu(5文字):見積“枚数”の配列zairyo(6文字):使用“材料”の配列rows(4文字):出力レコード配列wk(2文字):ダミー評価用(結果は使わない)- ループ変数
m,z(各1文字)
いずれもフィールドコードと重複せず、6文字以内で役割が伝わる命名にしています。
あなた:
コメントは10文字以内で
rex0220 計算式プラグインの使い方 の発言:
了解です。コメントを10文字以内にした版はこちらです![]()
LET(
maisu, JSON_P(OTVAL(見積枚数)), // 枚数取込
zairyo, JSON_P(OTVAL(使用材料)), // 材料取込
rows, ARRAY(), // 出力用
wk, ARRAY_MAP(maisu,m, // 外側回
ARRAY_MAP(zairyo,z, // 内側回
FSET(rows, ARRAY(rows,
DIC(
"枚数T", DIC_ITEM(m,"枚数"),
"材料名T", DIC_ITEM(z,"材料名")
)
))
)
),
TABLE_DATA(rows)
)
あなた:
計算式の解説を
rex0220 計算式プラグインの使い方 の発言:
もちろんです。
上記の計算式の目的は、2つのテーブル(「見積枚数」と「使用材料」)から、組み合わせテーブルを作ることです。
つまり、「見積枚数 × 使用材料」の全ての組み合わせを新しいテーブルとして生成しています。
式の全体構造
LET(
maisu, JSON_P(OTVAL(見積枚数)), // 枚数テーブル配列
zairyo, JSON_P(OTVAL(使用材料)), // 材料テーブル配列
rows, ARRAY(), // 出力用配列
wk, ARRAY_MAP(maisu,m, // 外側ループ
ARRAY_MAP(zairyo,z, // 内側ループ
FSET(rows, ARRAY(rows,
DIC(
"枚数T", DIC_ITEM(m,"枚数"),
"材料名T", DIC_ITEM(z,"材料名")
)
))
)
),
TABLE_DATA(rows) // テーブルデータ返却
)
各部分の解説
| 変数 | 内容 | 説明 |
|---|---|---|
maisu |
JSON_P(OTVAL(見積枚数)) |
「見積枚数」テーブルを配列として取得 |
zairyo |
JSON_P(OTVAL(使用材料)) |
「使用材料」テーブルを配列として取得 |
rows |
ARRAY() |
出力結果を格納するための空配列 |
wk |
ARRAY_MAP(...) |
2重ループ処理(結果は使わない) |
TABLE_DATA(rows) |
最終的に作った配列をテーブル形式に変換 |
2重ループの動き
ARRAY_MAP(maisu,m,
ARRAY_MAP(zairyo,z,
FSET(rows, ARRAY(rows,
DIC("枚数T",DIC_ITEM(m,"枚数"),"材料名T",DIC_ITEM(z,"材料名"))
))
)
)
- 外側 (
maisu):見積枚数テーブルの各行をmとして処理 - 内側 (
zairyo):使用材料テーブルの各行をzとして処理 - 組み合わせ生成:
各m(枚数)とz(材料)を組み合わせて、1行の辞書(DIC)を作成
結果はこのような形になります:
| 枚数T | 材料名T |
|---|---|
| 枚数1 | 材料A |
| 枚数1 | 材料B |
| 枚数2 | 材料A |
| 枚数2 | 材料B |
| … | … |
関数のポイント
| 関数 | 説明 |
|---|---|
OTVAL() |
他テーブルの値を取得 |
JSON_P() |
JSON文字列を配列化 |
ARRAY() |
空配列を生成 |
ARRAY_MAP() |
各要素に対して繰り返し処理 |
FSET() |
配列に要素を追加 |
DIC() |
辞書(オブジェクト)を作成 |
DIC_ITEM() |
辞書内の指定項目の値を取得 |
TABLE_DATA() |
配列をテーブル形式データに変換 |
この式の最終結果
- 出力テーブルには、見積枚数テーブルと使用材料テーブルの全組み合わせ行が生成されます。
- 組み立てたデータは「TABLE_DATA」で出力し、
他のフィールドに「テーブル型」で設定すれば、そのまま一覧表示できます。
希望があれば、この式を
「各材料ごとの合計枚数を集計する式」や
「条件付きで組み合わせを絞る式」
に発展させることもできます。
やってみますか?
あなた:
この計算式で改善できる点は?
rex0220 計算式プラグインの使い方 の発言:
思考時間: 40s
いい質問です。主に「無駄なループ更新を減らす」「空配列時のガード」「フィールドコードの明確化」で改善できます。
改善ポイント
- FSET呼び出し回数を削減
今は枚数×材料の全組合せぶんFSETしています。
外側ループ1回につきまとめてrowsへ結合すると速く・短くなります(ARRAYは配列同士をマージできます)。 - 空配列ガード
どちらかのテーブルが空なら即TABLE_DATA([])を返せば無駄計算を回避できます(ARRAY_MAPは要素ごとに処理するため)。 - フィールドコードの厳密化
DIC("枚数T",..., "材料名T",...)のキーはテーブル内項目のフィールドコードに合わせると安全です(ラベルではなくコードを使うのが原則)。 - コメントは10文字以内
ご要望どおり短く(既に対応済み)。
最適化後の式(FSET回数削減+空配列ガード)
LET(
maisu, JSON_P(OTVAL(見積枚数)), // 枚数取込
zairyo, JSON_P(OTVAL(使用材料)), // 材料取込
rows, ARRAY(), // 出力用
e, IF(ARRAY_COUNT(maisu)=0 || ARRAY_COUNT(zairyo)=0,
1, // 空ならスキップ
ARRAY_MAP(maisu,m, // 外側回
FSET(rows, ARRAY(rows,
ARRAY_MAP(zairyo,z, // 内側回
DIC(
"枚数T", DIC_ITEM(m,"枚数"),
"材料名T", DIC_ITEM(z,"材料名")
)
)
))
)
),
TABLE_DATA(rows) // 返却
)
- 外側1回につき
FSETも1回に圧縮(計 #枚数 回)。
ARRAY(rows, ARRAY_MAP(...))で配列をマージしているため、ネストせず平らに積めます。 ARRAY_MAPを使った配列処理の基本はこの流れ(配列→要素ごと関数適用)。
必要なら、出力キー("枚数T", "材料名T")を実際のフィールドコードに置き換えてご利用ください。
あなた:
テーブルには1行以上存在するので、下記の判定は不要 IF(ARRAY_COUNT(maisu)=0 || ARRAY_COUNT(zairyo)=0,
rex0220 計算式プラグインの使い方 の発言:
はい、その通りです。
「見積枚数」「使用材料」テーブルの両方に必ず1行以上ある前提であれば、
空配列チェック(IF(ARRAY_COUNT(...)=0 ...))は不要です。
したがって、よりシンプルで効率的な最適版は以下になります![]()
改善後の計算式(空チェック削除・FSET回数削減)
LET(
maisu, JSON_P(OTVAL(見積枚数)), // 枚数取込
zairyo, JSON_P(OTVAL(使用材料)), // 材料取込
rows, ARRAY(), // 出力用
wk, ARRAY_MAP(maisu,m, // 外側回
FSET(rows, ARRAY(rows,
ARRAY_MAP(zairyo,z, // 内側回
DIC(
"枚数T", DIC_ITEM(m,"枚数"),
"材料名T", DIC_ITEM(z,"材料名")
)
)
))
),
TABLE_DATA(rows) // 出力
)
この改善のポイント
| 改善項目 | 内容 | 効果 |
|---|---|---|
| FSET回数削減 | 外側ループ1回ごとにまとめて追加 | 実行速度向上(内部ループ回数分のFSETを削減) |
| 不要なIF削除 | 常に1行以上ある前提なので判定不要 | 式が短く・読みやすくなる |
| 短い変数名維持 | maisu, zairyo, rows, wk |
可読性と制約(6文字以内)の両立 |
結果の動き(簡易イメージ)
- 「見積枚数」テーブルに3行
- 「使用材料」テーブルに2行
→ 結果:3×2=6行の組み合わせが出力されます。
| 枚数T | 材料名T |
|---|---|
| 枚数1 | 材料A |
| 枚数1 | 材料B |
| 枚数2 | 材料A |
| 枚数2 | 材料B |
| 枚数3 | 材料A |
| 枚数3 | 材料B |
この形が、現時点で最短・最速・可読性のバランスが取れた式です。