CustomList

前々回の記事”Tips ‘n’ Tricks (パート3)”でTip #10として紹介したカスタム関数CustomListについて興味を持ったので、オリジナルの記事の方も見てみました。Kevin Frankさんも「この関数だけは特別」と激賞しているので、カスタム関数を使ったことがないという方も、これをきっかけにトライしてみてはいかがでしょうか。


FileMaker Hacks logo

CustomList

(元記事はこちら)

Kevin Frank
2016/9/20

今年(2016年)の記事”バーチャルリストによるレポート生成(パート1)”の中で、私はAgnès BarouhによるCustomListというカスタム関数を使っていくつかの基本的なリストを生成し、次のようにコメントしました。

2016-09-19_000003
ここで紹介したのはこの素晴らしいカスタム関数でできることのもっとも簡単な例です。普段はカスタム関数を使わないようにしているという方も、これだけは例外にすることをお勧めします。

今回の記事ではその主張が正しかったということを示したいと思います。CustomListをまだ知らないという方に簡単に説明すると、この関数はFileMakerの計算エンジンの機能をフルに活用して、連続したリストを生成/解析することができます。CustomListは最大500,000行まで処理することが可能です。再帰処理ではなく非常に高速です。今回は実世界と理論上でのさまざまな問題を解決するために、この関数を使用していきます。[実際には、行数の制限は調整可能で、実行環境によっても異なります。詳細はカスタム関数の定義を参照してください。]

今回の記事では以下の4つのデモを示します。

…その他にも、わざわざデモを示さなくても説明できる例も合わせていくつか紹介します。

基本的な使い方

最初に基本的な構成を見てみましょう。CustomListは3つの引数を取ります。

CustomList ( Start ; End ; Function )

  • Start:  正の整数
  • End:  Startと同じかそれ以上の正の整数
  • Function:  n回繰り返される計算式。ここでnは(End – Start + 1)となる。
    なお、この計算式は引用符で囲む。

CustomListを非常に強力なものにしているのは、この[n]をつかった繰返しです。nは1から始まり、StartからEndまでの間を1ずつ増加する、魔法の小さなカウンタです。[n]を必ず使わなくてはいけないわけではないということに注意してください。例えば、次の式ではUUIDのリストを生成できます。

2016-09-19_114802

しかしほとんどの場合、実行される行が現在の反復回数を認識するため、[n]を使用することが多いでしょう。[n]はそれ自体では1ずつ増加しますが、FileMakerの関数と演算子を任意に組み合わせて、任意の増分値を設定することができます。たとえば、1から始めて2乗を10回繰返す、あるいは2のべき乗を1から10に対して生成するなどが可能です。

2016-09-19_120144

[n]が結果の値に明示的に現れることもあります。以下の例では、桁数に応じて頭にゼロを付けています。計算式が引用符で囲まれているので、式自体に含まれる引用符はエスケープ処理が必要です。

2016-09-19_161728

最初の出会い

私は8年前に初めてCustomListを使いましたが、そのときの用途はxmChartのx軸に88週間分のラベルをつけるためでした(間が詰まりすぎているので隔週、つまり44個の値が表示されています)。

ここでは、5月1日から翌年の終わりまで14日置きに日付を表示しようとしています(グラフの目的は、比較のために複数年のデータを重ね合わせることにあったため、あえて年の表示を消しています)。

//   note: the years are irrelevant... but avoid leap years
Substitute ( 
     CustomList ( 1 ; 44 ; "Date ( 5 ; 1 ; 2009 ) - 14 + [n] * 14" ) ; 
     ["/2009" ; ""] ; ["/2010" ; ""] 
)

いくつかの基本的な例を示したので、次はデモに進みます。

デモ1: 対象レコードに基づくリスト

2016-09-19_122131

ここでの課題は、対象レコードのセットで現在のソート順(未ソートの場合も)を反映して、学生の名前と学年のリストを作成すること(あるリストから対応した別のリストを作るミラーリング)です。生徒の名前は、姓(Last Name)、名(First Name)の順に、なお希望する通称(Preferred Name)が入力されていれば、名に代えてそちらを使います。

以下が標準的なミラーリングの計算式(非保存のテキスト)です。

2016-09-19_135107

…そして、以下に示すのが逆ミラーリング(Reverse Mirroring)の計算式です。主な違いは、GetNthRecordに渡される2番目の引数です。これにより、EndからStartへ逆方向に反復されます。

2016-09-19_135810

スクリプトで使う変数($x)をなぜここで使うのかと疑問に思っている方に対しては、CustomListを呼び出す前にLetを使って変数を宣言するやり方は一般的なものだと説明しておきます。標準的なLet関数用の変数($または$$が付いていない変数)を使うとCustomListからは見えません。

カスタム関数の定義から引用した以下の部分は、CustomListによって作成される各行がこの関数の中のLet節の中で生成されることを説明しています。これらのLet節を私はLet bubbles(泡)と呼んでいます。

基本的にCustomList()は2つのことを行う :
1/ 計算式を連結された文字列に変換する :
したがって 
CustomList ( 1; 4; "GetNthRecord ( Field ; [n])") 
は以下に変換される
"Let ([ CLNum = 1 ] ; GetNthRecord ( Field ; CLNum )) & ¶ &
Let ([ CLNum = 2 ] ; GetNthRecord ( Field ; CLNum )) & ¶ &
Let ([ CLNum = 3 ] ; GetNthRecord ( Field ; CLNum )) & ¶ &
Let ([ CLNum = 4 ] ; GetNthRecord ( Field ; CLNum ))"

2/ この文字列をevaluateする

そのため、外で宣言された変数がCustomListから見えるように、変数には$varまたは$$varを使用します。また、Reverse Mirroringの計算式の最後にあるLet ( $x = "" ; "" )のように、終了時に変数をクリアします。これには、a)メモリを解放する、b)予期しない悪いことが起こることを防ぐ、の2つの目的があります。

小休憩1: MiddleValuesの置き換え

MiddleValues関数を使うときに、FileMakerが「親切に」値の後ろに改行を付けてくれるという仕様に悩まされたことはないでしょうか? 代わりにこれを使えばもう悩む必要はありません。例えば変数$theListに値”A¶B¶C¶D¶E¶F¶G¶H¶I¶J¶K”が入っているとします。

2016-09-20_000111

そしてもちろんこのテクニックを使えば、LeftValuesはもちろん、少し調整すればRightValues(この関数も余計な改行を付けてくれます)も簡単に置き換えることができます。

デモ2: 一致する値の合計

これは、FileMakerのディスカッションフォーラムの1つに投稿された課題に対して考えられたものです。2つのリストがあって、それぞれの要素が1対1で対応しています。1つめのリストのある要素を選択したときに、対応する2番目のリストの対応するすべての値を合計するにはどうするか、という問題です。

2016-09-19_160617

以下がその実現方法です。

2016-09-23_170350

説明:

1. 2つのリストの要素を1つのリストにまとめる

2016-09-19_173617

2. 行の左側の文字が指定された文字と一致する行から、右側の数字だけを含む新しいリストを生成する。例えば“C”の場合、結果は 7¶7¶7

3. Substituteを使って、前の結果を7+7+7に変換する

4. Evaluate ( 7+7+7 )

小休憩2: 階乗関数の改良版

FileMakerネイティブのFactorial関数は最大212までの階乗を計算できます(ただし、Jason DeLoozeがこの制限を回避する方法をFun With Factorialsで紹介しています)。CustomListを使用すると、374までの階乗をそのまま計算することができます。さらに増やす必要がある場合は、Jasonの回避策を利用できます。

2016-09-19_192743

説明:

1. 1ずつ減る数のリストを生成する: 361¶360¶359¶358…

2. Substituteを使用して、上記の文字列を361*360*359*358…に変換する

3. Evaluate ( 361*360*359*358… )

[実際には、1から361まで増分させる方が簡単で同じ結果を得られますが、減分させるほうが階乗らしくなります]

デモ3: 日付のフィルタリング

2016-09-19_174454

このデモの最終的な目標は、指定した学年度(“Begins”から”Ends”までの期間)の月曜日の日付の値リストを生成して、正しい順にポップアップメニューに表示することです。

ただしここで、休暇中の月曜日は除く必要があります。”No School”というポータルを見ればわかるように、学年度中に約1週間の休暇が5回(そのうちの2つは12月の後半に連続して)発生します。

まず始めにすべての月曜日のリストを作成します(休暇中かどうかにかかわらず)。

2016-09-19_181312

次に除外する月曜日のリストを生成します。

2016-09-19_181705

これは以下の計算式で求めます。

2016-09-19_182119

そして最後に、Bruce RobertsonのAntiFilterValuesを使用して、1つ目のリストから2つ目のリストを「減算」して、有効な月曜日のみを残します(その週の間に学校がある場合、その月曜日は有効と見なします)。以下が有効な月曜日の日付リストです。

2016-09-22_093635

そして、その求め方は以下の通りです。

2016-09-24_025127

小休憩3: CustomListがCustomListを呼び出す

今回のCustomListのオデッセイ(Odyssey; 長い冒険旅行)も終わりに近づいたので、カスタム関数が自分自身を呼び出す(つまり、リストのリストを生成する)例をいくつか示します。この最初の例では、内側のリストはコンマ区切りです。

2016-09-20_000000

次の目標は、それぞれ01から03までの番号が付けられた2つのグループのUUIDを作成します。

2016-09-19_191444

あるいは、この問題はCustomListを一度使うだけでも解くことができます。

2016-09-19_191911

CustomListが自分自身を呼び出すというトピックに戻って、今回の最後のデモでは、このテクニックを使って素数のコンマ区切りのリストを生成します。

デモ4: 素数ジェネレータ

2016-09-19_184932

基本的な考え方: 前述のAntiFilterValuesを利用して、一連の整数を遅延的にエラトステネスのふるいにかけてスタックに積み上げていきます。これについてはきっと改善の余地があるので、その提案をお待ちしています。

説明:

1. 2から上限までのすべての整数のリストを生成する

2. 2から上限までのすべての合成数(非素数)のリストを生成する

3. AntiFilterValuesを使用してそれらをフィルター処理し、改行をコンマに置き換える

まとめ

今回の目的は、CustomListを使ってできることの幅の広さと奥の深さについて、イメージを持っていただくことでした。このカスタム関数がFileMakerのツールボックスに入れる価値がある強力で柔軟なツールであるという事実と比べたら、私がここで示した具体例は、まったく重要ではありません。CustomListを使用して面白い問題を解決したという方は、ぜひこの記事にコメントを投稿し、どんな問題だったか、それをどのように解決したかを共有してください。Good luck and Happy FileMaking.

 

 

 

 

 

 

 

Leave a Reply