初心者のFileMaker pro Q&A (旧掲示板)

みんなに優しく、解りやすくをモットーに開設しています。 以下のルールを守りみんなで助け合いましょう。

1.ファイルメーカーで解らない事があればここで質問して下さい。 何方でも、ご質問・ご回答お願いします。 (優しく回答しましょう)

You are not logged in.

Announcement

新しい掲示板は、こちら:https://fm-aid.com/forum/t/filemaker


#1 2017-06-27 23:55:38

bon
Member

リスト内容の整理をするカスタム関数

環境はWin10でFM Pro Advance 14 を使用しています。

リスト内の文字列を自動で整理する関数を作ってみましたが、
再帰式を理解できず、困ってます。
また、最も軽く動作してくれる関数とするのにどうしたらよいでしょうか?
最大かつ最速処理の為にEvaluate関数やQuote関数を用いた方が良い様ですが、
これも使い所がピンときません。
ファイルメーカーの方にマルチコアCPUのコア数が多い方が処理が速いと聞きましたが、
CPUを交換する前に、少しでも処理が速くなる式を書けるようになりたいです。

ご面倒でしょうが、よろしくご教授お願いいたします。

リスト内容を整理する際に
・空白は除く。
・完全一致の重複文字列は除く。
・各行の文字列の前後の空白は除く。
・計算式やスクリプトや他のカスタム関数でも使える。
上記の仕様にしています。

動作としては、
<対象リスト>

あい

あぃ
あかい
  ←ここは空白
あい

<関数結果>

あい
あぃ
あかい
となる関数です。

目的を達する為に2つカスタム関数を作っています。

○カスタム関数「@GVT」・・・リストから指定位置の文字列を取り出す。
〔関数の引数〕
リスト・・・対象リスト
位置・・・リストの行の位置、フィールドの値がテキストでも使える
※リストと位置の値が空白の際は空白を返す、位置がリスト内の行数を超す場合は空白を返す。GetValue関数で値番号が0の時に値一覧の1行目が返されてしまうと本にあったので回避したい。

〔動作として〕
上述の対象リストの5行目を返す場合は、@GVT ( 対象リスト ; "5行目" )として、結果は あかい となります。

Case ( IsEmpty ( リスト ) ; "" ; IsEmpty ( 位置 ) ; "" ;
Let ( [
位 = GetAsNumber ( RomanHankaku ( 位置 ) ) ;  ←位置がテキストの際、テキスト内から数値にあたる部分を半角の数字として取得。
値 = GetValue ( リスト ; 位 ) ] ;  ←GetValueで指定位置の文字列を取得する。
Case (
IsEmpty ( 位 ) ; "" ; ←位置がテキストではあるが数値ではない場合に空白を返す。
位 = 0 ; "" ;  ←位置が0の場合に空白を返す。
位 ≠ Int ( 位 ) ; "" ;  ←位置が小数の場合に空白を返す。
位 > ValueCount ( リスト ) ; "" ;  ←位置が行数を超す場合は空白を返す。
IsEmpty ( 値 ) ; "" ;  ←取得した文字列が単順に空白の場合は空白を返す。
Substitute ( Trim ( 値 ) ; ¶ ; "" ) ←取得した文字列の前後の空白を除く、また、除いた結果が空白の際は空白を返す。
) ) )
【この関数の問題点として】
多用した際に、軽く動いて欲しいのと、本には値一覧の数以上の値番号を与えると空白が返されます。とあったが、
参考にしている本に多数の間違いが有るので助長しており、最も軽く動作してくれるか不安です。

○カスタム関数「@List」・・・リスト内容を整理する関数
〔関数の引数〕
リスト・・・対象リスト
※@List ( 対象リスト )とすれば、<関数結果>が得られます。

Case (
IsEmpty ( リスト ) ; "" ;
Let ( [
対 = Trim ( リスト ) ; ←リストの前後の空白を削除。
置 = "ΘΘΘΘΘΘΘ" ; ←置き換えの際に変にならないよう記号にしてみました。
α001 = @GVT ( 対 ; 1 ) ;
α002 = List ( α001 ; Case ( IsEmpty ( FilterValues ( Substitute ( α001 ; @GVT ( 対 ; 2 ) ; 置 ) ; 置 ) ) ; @GVT ( 対 ; 2 ) ; "" ) ) ;
α003 = List ( α002 ; Case ( IsEmpty ( FilterValues ( Substitute ( α002 ; @GVT ( 対 ; 3 ) ; 置 ) ; 置 ) ) ; @GVT ( 対 ; 3 ) ; "" ) ) ;
α004 = List ( α003 ; Case ( IsEmpty ( FilterValues ( Substitute ( α003 ; @GVT ( 対 ; 4 ) ; 置 ) ; 置 ) ) ; @GVT ( 対 ; 4 ) ; "" ) ) ;
α005 = List ( α004 ; Case ( IsEmpty ( FilterValues ( Substitute ( α004 ; @GVT ( 対 ; 5 ) ; 置 ) ; 置 ) ) ; @GVT ( 対 ; 5 ) ; "" ) ) ;
α006 = List ( α005 ; Case ( IsEmpty ( FilterValues ( Substitute ( α005 ; @GVT ( 対 ; 6 ) ; 置 ) ; 置 ) ) ; @GVT ( 対 ; 6 ) ; "" ) ) ;
つづく
α200 = List ( α199 ; Case ( IsEmpty ( FilterValues ( Substitute ( α199 ; @GVT ( 対 ; 200 ) ; 置 ) ; 置 ) ) ; @GVT ( 対 ; 200 ) ; "" ) ) ;
E = α200 ] ;
E ) )

※α006 = List ( α005 ; Case ( IsEmpty ( FilterValues ( Substitute ( α005 ; @GVT ( 対 ; 6 ) ; 置 ) ; 置 ) ) ; @GVT ( 対 ; 6 ) ; "" ) )を例として説明すると
5行目までで整理したリストα005に6行目の文字列が存在しない場合は、α005のリストに6行目の文字列を加える。
FilterValuesを用いているのは、Substituteでα005のリストに6行目の文字列があった場合には記号に置換えてから、リストから記号を抽出する際に、完全一致の文字列として抽出するためです。

【この関数の問題点として】
実際に200行のリストで動作確認していないですが、字数制限の為、200行目までしか記述できない事です。

Offline

#2 2017-06-28 00:12:27

Shin
Member

Re: リスト内容の整理をするカスタム関数

FM16からサポートされた、UniqueValues() と SortValues() の機能そのものの様に思うのですが。

Offline

#3 2017-06-28 02:03:11

bon
Member

Re: リスト内容の整理をするカスタム関数

Shinさん、ご返答ありがとうございます。

FM16からサポートされた関数に同じものがあったのですね。
今回の私のクリアすべきテーマは「最大かつ最速処理の回帰式スクリプトを書くために、どの様に考え、記述したら良いか?」なので、
同様の機能の関数がサポートされた事でモチベーションが下がるようでしたら、別のカスタム関数に変更した方が良いでしょうか?
質問を書くのに2時間位かかったのですが、わかりにくい所はありますか?

次にチェックできるのは6/29(木)の夕方以降になりそうです。

【蛇足です】
FM Pro Advance 14 で、もっと勉強してからにするつもりでノーチェックでした。
個人で購入しなくちゃなので、薄い財布の為にチェックだけしかできないのがツライ・・・
個人的には下記の点が気になります。
・Filter関数・ValueFilter関数・PatternCount関数・Position関数も全角・半角・大文字・小文字の完全一致でない事。
→完全一致と部分一致の使い分けくらいの機能はあっても罪にはならないと思う。
・NumToJText関数が不便で、数値が1億以上だと累乗表記になったりで、Substituteで簡単に置換できない事。
→簡単に計算ができない。銀行や不動産や証券や保険業の額面が大きい所は扱いづらいのでは?と感じます。
ついでに、小数部分も日本語に変換したら良いのにね。
・GetValue関数は有るのに、値一覧から値番号を取得する関数が無い事。
・Int関数は有るのに小数部分のみを取り出す関数が無い事。
→単純に対称となる関数の無い事への疑問。
特に数値に関しては、そろそろ改善して欲しいと思っています。
改善したかとFM Pro Advance 14購入してがっかりだったので、改善されたら購入貯金始めます。
蛇足内容はFM16をチェックしたのちファイルメーカー社に要望として出してみます。

Offline

#4 2017-06-28 02:27:18

Hiro
Member

Re: リスト内容の整理をするカスタム関数

その後の#3説明の主旨とは違ってしまいましたが、一応当初の質問事例に対しては、

>> リスト内容を整理する際に
   → カスタム関数など特殊機能は使わず、標準機能でできる簡便法

> ・空白は除く。
   → 「値一覧」機能を利用
> ・完全一致の重複文字列は除く。
   → 「値一覧」機能の「Unicode」索引オプションを利用
> ・各行の文字列の前後の空白は除く。
   → リストを繰り返しフィールドに持ち替えて、その際に trim 処理
> ・計算式やスクリプトや他のカスタム関数でも使える。
   → 「値一覧」や「繰り返し計算フィールド」、「レコードID」計算フィールドなどの事前設定は必要だが、
   → 結果値は ValueListItems 関数のみで自動計算取得

>> 上記の仕様にしています。
   → ※この簡便法の難点は、結果リストの順番が、Unicodeの文字コード番号順になることです。


●簡便法サンプル「ユニーク値化リスト一覧.fmp12」→ https://yahoo.jp/box/GyaLFG

Offline

#5 2017-06-28 12:43:57

Hiro
Member

Re: リスト内容の整理をするカスタム関数

ループ計算式による方法、を追加補足
(ただし、対象リストの行数は 200s 行程度以下に限定)
(超える場合は、等価ロジックのカスタム関数に組替えます)
特徴は、
・計算式だけで取得できる、事前の設定などは一切不要
・Unicodeによる完全一致で文字列比較ができる、大/小・全角/半角などを区別
・元リストの順番に準じた結果リストを得ることができる

Let([
   $lst=リストフィールド;
   $i=0;
   $res="";
   $uni="";
   $fnc=
      "Case($i=ValueCount($lst); $res;
         Let([
            $i=$i+1;
            #itm=Trim(GetValue($lst; $i));
            #add=Case(FilterValues($uni; Code(#itm))=\"\"; #itm);
            $res=List($res; #add);
            $uni=List($uni; Code(#add))
         ]; Evaluate($fnc))
      )"
];
   Evaluate($fnc)
)

Offline

#6 2017-06-28 17:16:09

bon
Member

Re: リスト内容の整理をするカスタム関数

Hiroさん、ご回答ありがとうございます。
気になって会社来てみて良かったです。
簡便法サンプルについては昨夜に、過去ログからダウンロードさせて頂きました。
内容についての理解は至らずなので、明日から調べたりしてみて、解らない所は質問してみます。
ループ計算式による方法
については特徴が欲しい動作と結果に合致していて、うれしいです。

簡便法のサンプルから勉強して、ループ計算式の理解に至れればと思います。
いろいろ試してみるのに時間が必要です。
一旦、この質問に関しては解決とさせて頂き、解らない所は新しい質問をするようにします。

お答え頂けた皆様、ありがとうございました。

Offline

#7 2017-06-28 18:48:54

bon
Member

Re: リスト内容の整理をするカスタム関数

UniqueValues関数はUnicodeを利用して完全一致を実現し、重複を除けるようですね。
GetValue関数の逆の作用をする関数もあれば対称的で良いのにと思いました。
逆GetValue関数 ( 値一覧 ; 文字列 ) = "値番号¶値番号¶値番号・・・・"
<値一覧>

あい

あぃ
<文字列>

逆GetValue関数 ( 値一覧 ; あ ) = "1¶3"

Offline

#8 2017-06-28 20:31:55

Hiro
Member

Re: リスト内容の整理をするカスタム関数

ループ式を一度マスターすれば、用途は無限です。
例えば、逆GetValue関数も簡単に作れます。

#5のループ式を改造した作例は、以下
(Exact関数で完全一致の文字列比較をしています)

Let([
   $lst=リストフィールド;
   $kwd=検索キーワードフィールド;
   $i=0;
   $res="";
   $fnc=
      "Case($i=ValueCount($lst); $res;
         Let([
            $i=$i+1;
            #itm=GetValue($lst; $i);
            #add=Case(Exact(#itm; $kwd); $i);
            $res=List($res; #add)
         ]; Evaluate($fnc))
      )"
];
   Evaluate($fnc)
)

Offline

#9 2017-06-29 17:46:49

bon
Member

Re: リスト内容の整理をするカスタム関数

Hiroさん、ご回答ありがとうございます。

Hiro wrote:

ループ式を一度マスターすれば、用途は無限です。

とのお言葉、モチベーションが上がります。
しっかり理解しようと思います。

まずは、簡便法のところを理解しよう(7月中)と思います。
次に、ループ式について理解しよう(8月~9月位はかかるかな)と思います。
ループ式についての作例2つを比較しながら考えられそうなので助かります。

Offline

#10 2017-07-01 21:18:57

bon
Member

Re: リスト内容の整理をするカスタム関数

Hiroさんから御提示いただきました簡便法につき、理解に至らない点があります。

※Hiroさんと同じに作ると、もちろん、ちゃんと動きます。
※理解する上で、わからなくなったので質問です。
→お手隙の時に、ご回答等、お付き合い頂けますとありがたいです。

○新規作成する事で再現と検証してみて、試してみました。

質問1、Get ( 計算式繰り返し位置番号 )の使い所や説明として、事例の多いホームページがあれば誰か教えて頂きたいです。
質問2、フィールド「リスト配列」[タイプ:計算式(繰り返し200)]の考え方が分かりません。

○フィールド「リスト配列」
【オプション設定】
[式]
Trim(
GetValue(リスト[1]; Get(計算式繰り返し位置番号))
)

→リスト[1]の[1]は繰り返しフィールドの繰り返し内容の取得と考えて実験してみました。
[実験1]Trim( GetValue( GetRepetition ( リスト ; 1 ) ; Get ( 計算式繰り返し位置番号 ) ) )に置換えてみた。
      結果→置換えても同じになった。
→では、リストは繰り返しフィールドではないけど、リストフィールドだからかと考え、試してみました。
[実験2]Trim( GetValue( GetValue( リスト ; 1 ) ; Get ( 計算式繰り返し位置番号 ) ) )に置換えられる?
      結果→1行目にリストの1行目が表示され、2行目以下は空白。
[実験3]Trim( GetValue( リスト ; Get ( 計算式繰り返し位置番号 ) ) )の場合はどうか?
      結果→1行目にリストの1行目が表示され、2行目以下は空白。
→結果から、Get ( 計算式繰り返し位置番号 )が関係している!と思うのですが、ググってもピンとくる説明が見つかりません。
    ↓
よって、Get ( 計算式繰り返し位置番号 )の使い所や説明として、事例の多いホームページがあれば誰か教えて頂きたいです。

今、ここで詰まってしまいました。
試してみて、自己連結リレーションにしたら、
・from マスタ 等が表示されるようになった。
・レイアウトで、繰り返しフィールドは「繰り返し数を表示」で表示する行数を指定することを理解した。
・何故かわからないが、フィールド名「値一覧リスト」と値一覧名「値一覧リスト」が同じじゃないと、フィールド「値一覧リスト」が空白になる。
のに、何となく気づきました。上記の質問が未解決ですが、

質問3、フィールド「値一覧リスト」の考え方が分かりません。

○フィールド「値一覧リスト」
【オプション設定】
[式]
ValueListItems( Get ( ファイル名 ) ; "値一覧リスト" ) & Left( リスト ; 0 )

試してみた↓
・ Get ( ファイル名 )で直接テーブル名を指定した場合→ダメ・・・なぜ?
・ "値一覧リスト"を値一覧名を変えてみた→ダメ・・・値一覧の値をターゲットにしている!かな?
よって、
ValueListItems( ファイル名 ; 値一覧名 ) のFMの説明の<値一覧> にあるすべての値を改行で区切って返します。がわからなくなりました。

ファイル名で指定した中の、値一覧名にある値を返すのでは?→値一覧名がフィールド名と違っていても返すのでは?→フィールド名と値一覧名が一致する必要があるのか?

となりまして、どなたか考え方を教えて下されば助かります。
※結果としてなるんや!ではなく、できれば論理的にお願いする次第です。

質問4、【索引オプション】の「計算結果を保存せず必要時に再計算するにする」にする意味で重要なことはありますか?
[実験3]非保存フィールドを「必要時索引を設定」にしてみたが、結果は同じだった。

質問5、& Left( Aリスト ; 0 )の意味は?

Offline

#11 2017-07-02 01:40:10

Hiro
Member

Re: リスト内容の整理をするカスタム関数

> 質問1、Get ( 計算式繰り返し位置番号 )の使い所や説明として、事例の多いホームページがあれば誰か教えて頂きたいです。
・ほぼ、無いと思います。ヘルプの関数リファレンスを調べて、なお解らない点はここに問合わせるのが良いかな。

> 質問2、フィールド「リスト配列」[タイプ:計算式(繰り返し200)]の考え方が分かりません。
>
> ○フィールド「リスト配列」
>  【オプション設定】
>  [式]
> Trim(
>  GetValue(リスト[1]; Get(計算式繰り返し位置番号))
> )
>
> →リスト[1]の[1]は繰り返しフィールドの繰り返し内容の取得と考えて実験してみました。
・いいえ、そうではありません。
・繰り返しフィールド内から外部の繰り返し・標準フィールドを参照する場合の明記マーカです。
・繰り返しフィールドは繰り返し同士がデフォルト仕様の為、標準フィールドも繰り返し[1回]フィールドと表現・明示するわけですネ。
・これは Extend関数 の簡略法で等価の働きです。
・明記しないで省略すると、FMは繰り返しフィールド同士と判断し、同じ番号位置データを参照する仕様です。
・▼以下の3つの実験と結果判断は、上記仕様説明を踏まえて再考察してみて下さい。特に、1コマ目しか参照しない結果を!
>  [実験1]Trim( GetValue( GetRepetition ( リスト ; 1 ) ; Get ( 計算式繰り返し位置番号 ) ) )に置換えてみた。
>       結果→置換えても同じになった。
> →では、リストは繰り返しフィールドではないけど、リストフィールドだからかと考え、試してみました。
>  [実験2]Trim( GetValue( GetValue( リスト ; 1 ) ; Get ( 計算式繰り返し位置番号 ) ) )に置換えられる?
>       結果→1行目にリストの1行目が表示され、2行目以下は空白。
・2コマ目以下が見に行っても相手側(標準フィールド)に2コマ目以下が無いという事です。
>  [実験3]Trim( GetValue( リスト ; Get ( 計算式繰り返し位置番号 ) ) )の場合はどうか?
>       結果→1行目にリストの1行目が表示され、2行目以下は空白。
・2コマ目以下が見に行っても相手側(標準フィールド)に2コマ目以下が無いという事です。
> →結果から、Get ( 計算式繰り返し位置番号 )が関係している!と思うのですが、ググってもピンとくる説明が見つかりません。
・関係ありません。
>     ↓
> よって、Get ( 計算式繰り返し位置番号 )の使い所や説明として、事例の多いホームページがあれば誰か教えて頂きたいです。
・テスト用ファイルで、「繰り返しフィールド」と「繰り返しフィールド」、「繰り返しフィールド」と「標準フィールド」、の2つのケースで、軽く挙動テストしてみるのが早道かも。

> 今、ここで詰まってしまいました。
> 試してみて、自己連結リレーションにしたら、
> ・from マスタ 等が表示されるようになった。
> ・レイアウトで、繰り返しフィールドは「繰り返し数を表示」で表示する行数を指定することを理解した。
> ・何故かわからないが、フィールド名「値一覧リスト」と値一覧名「値一覧リスト」が同じじゃないと、
> フィールド「値一覧リスト」が空白になる。
> のに、何となく気づきました。上記の質問が未解決ですが、
>
> 質問3、フィールド「値一覧リスト」の考え方が分かりません。
・所謂、動的値一覧で自己レコードの1フィールド内容のみで値一覧を作る、少し特殊な用法を採っています。

> ○フィールド「値一覧リスト」
>  【オプション設定】
>  [式]
>  ValueListItems( Get ( ファイル名 ) ; "値一覧リスト" ) & Left( リスト ; 0 )
>
> 試してみた↓
>  ・ Get ( ファイル名 )で直接テーブル名を指定した場合→ダメ・・・なぜ?
・テキストは「"」で囲むこと。→ "ファイル名"
> ・ "値一覧リスト"を値一覧名を変えてみた→ダメ・・・値一覧の値をターゲットにしている!かな?
・そうです。「値一覧の設定」の際に登録した名前です。テキストだから「"」で囲み → "値一覧の登録名"
よって、
> ValueListItems( ファイル名 ; 値一覧名 ) のFMの説明の<値一覧> にあるすべての値を改行で区切って返します。がわからなくなりました。
・「ファイル名」→ Get(ファイル名) にしているのは、例えファイル名を変更した場合でも、新名へ自動更新され安心安全だからです。
・「値一覧名」は、値一覧の設定」の際に登録した名前です。テキストだから「"」で囲み → "値一覧の登録名"
>
> ファイル名で指定した中の、値一覧名にある値を返すのでは?→値一覧名がフィールド名と違っていても返すのでは?→フィールド名と値一覧名が一致する必要があるのか?
・一致・不一致は全く不問です。サンプルでは両者のデータ内容が同じなので同じ名前にしたという事で、他意は有りません。
>
> となりまして、どなたか考え方を教えて下されば助かります。
> ※結果としてなるんや!ではなく、できれば論理的にお願いする次第です。
>
> 質問4、【索引オプション】の「計算結果を保存せず必要時に再計算するにする」にする意味で重要なことはありますか?
>  [実験3]非保存フィールドを「必要時索引を設定」にしてみたが、結果は同じだった。
・値一覧の内容が変更されても更新されないのを防ぐためです。
>
> 質問5、& Left( Aリスト ; 0 )の意味は?
・(ちょっとトリッキーな用法)式全体の自動更新・再計算を誘発するための起動トリガー要素です。
・計算結果は常に「無」ですが、「Aリスト 」のデータ編集で再計算を誘発します。

Offline

#12 2017-07-02 02:59:31

bon
Member

Re: リスト内容の整理をするカスタム関数

Hiroさん、とても丁寧に書いて頂きまして、お手間おかけして申し訳ありません。

お答えをヒントに、理解できるよう頑張ってみます。

・質問1に至る考え方が間違っていたので、Hiroさんのご回答に至れるように学習やり直してみます。
※試してみる時間を沢山下さい。すぐには理解できないので・・・
  なお、ファイルメーカーのヘルプの関数リファレンスは、今回の関数については全て読んではみました・・・

蛇足です。)Hiroさんのカラフルな記述はとても読みやすいと思いました。
質問する側として、読みやすくする努力はしたいですが、まず、質問内容の事で手一杯です。ご容赦下さい。
ご返答頂いた時間からして、お手間とお時間をかけて頂き、申し訳なく思います。
今は、頭も回らなくなってきたので、ひとまず寝てから、いろいろ試してみようと思います。

Offline

Registered users online in this topic: 0, guests: 1
[Bot] ClaudeBot

Board footer

Powered by FluxBB
Modified by Visman

[ Generated in 0.006 seconds, 9 queries executed - Memory usage: 602.57 KiB (Peak: 639.48 KiB) ]