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

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

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

You are not logged in.

Announcement

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


#1 2016-12-02 10:47:21

tcf775
Member

LetとEvaluateを使った再帰的な計算式について

OS:[Windows10]
FileMaker Ver:[15]

お世話になります。
ずっとシステム開発をやっていますが、
FileMakerについては勉強し始めの超初心者です。

HTMLの中から
あるタグの中の特定の属性の値を全て取り出して
重複しない値一覧を作る。
(例えば画像のURLだけとか)
という処理を計算式で
LetとEvaluateを使ってやってみようと思いとりあえず作ってみました。

以下の計算式で、とりあえず目的は達したんですが、
この計算式、何か冗長な気がしてなりません。
------------------------------------------------------------------
Let (
    [
         $sale_text = テキスト;
        $start_tag = タグ開始文字;
        $end_tag = タグ終端文字;
        $start_attr = 属性開始文字;
        $end_attr = 属性終了文字;
        $list_values = "";
        $start_pos = 1;
        $start_pos = Position ( $sale_text ; $start_tag ; 1 ; 1 );
        $saiki = "
            Case($start_pos > 0;
                Let (
                [
                    $text_length = Length ( $sale_text );
                    $sale_text = Right ( $sale_text ; $text_length - $start_pos + 1 );
                    $add_text = Left ( $sale_text ; Position($sale_text; $end_tag; 1; 1 ));
                    $start = Position($add_text; $start_attr; 1; 1) + Length($start_attr);
                    $end = Position($add_text; $end_attr; $start; 1);
                    $add_text = Middle($add_text; $start; $end - $start);
                    $add_text = Case( PatternCount($list_values; $add_text) = 0; $add_text & \"\¶\"; \"\");
                    $list_values = $list_values  & $add_text;
                    $sale_text = Middle( $sale_text; Position($sale_text; $end_tag; 1; 1 ); $text_length);
                    $start_pos = Position ( $sale_text ; $start_tag ; 1 ; 1 )
                ];
                Evaluate($saiki)
                );
                $list_values
            )
        ";
        $list_values = Evaluate($saiki)
    ];
    Left($list_values; Length($list_values) - 1)
)
-----------------------------------------------------------------------
カスタム関数を使う、スクリプトを使うなど
他にもやり方はあるのでしょうが、LetとEvaluateを使ってやるという場合に
こんなやり方がある。とか上の計算式をもっとこうしたほうが良いとか
アドバイスがあれば教えて頂きたいです。

曖昧な質問で申し訳ありませんが
ご教授、お願いいたします。

Last edited by tcf775 (2016-12-02 10:49:10)

Offline

#2 2016-12-02 11:27:19

Shin
Member

Re: LetとEvaluateを使った再帰的な計算式について

私なら、
$add_text = Case( PatternCount($list_values; $add_text) = 0; $list_values & \"\¶\"  & $add_text ; \"\");
$sale_text = Right( $sale_text; $text_length - Position($sale_text; $end_tag; 1; 1 ) );
を、にするかな、位でしょう。
また、全体の改行を全部取り去った上で、タグ開始文字 と タグ終端文字 の前後に改行を加えておき、それを探して文字列を探していく、という方法も面白いかも。

Offline

#3 2016-12-02 13:09:36

tcf775
Member

Re: LetとEvaluateを使った再帰的な計算式について

Shin 様

ご回答ありがとうございます。

確かに残りの文字を取り出すのに
MiddleよりはRightのほうが素直な気がしますね。

探しやすいように
最初に文字を置き換えるという発想はできてませんでした!!

参考にさせていただきます。
ありがとうございます :D

Offline

#4 2016-12-02 13:23:43

Hiro
Member

Re: LetとEvaluateを使った再帰的な計算式について

命題解決の基本ロジック部分の検討は取敢えず置いといて、
わたし的に気になるテクニカルな点を、まずは気ままに列挙、

・間違っても無限ループに陥らないよう、ループ抜け条件式は再帰"Case"式の最初に明示的記述した方が。
・リスト文字列の照合は、FilterValuesが安心、PatternCountは部分一致照合が心配。
・Caseのデフォルト値が空白をワザワザ\"\"エスケープ記載しなくても、
      デフォルト値指定そのものを省略してしまえば楽チンかと。
・リストに追加は、List関数が最適、「追加データ & ¶」は末尾空行の削除処理が面倒。
・全ての処理は定義式内で極力完結するよう努め、式全体の見通しを良くする。

ロジックの方は、後で思案した結果、代案があればまた投稿しますネ。

Last edited by Hiro (2016-12-02 13:42:25)

Offline

#5 2016-12-02 14:51:44

Shin
Member

Re: LetとEvaluateを使った再帰的な計算式について

全体の改行を全部取り去った上で、タグ開始文字 の後と タグ終端文字 の前に改行を加えておき増す。1行目を見て,各行の先頭に終端文字が有ればその行削除、開始文字で終わっていればその行削除(最初の1行だけのはず),どちらでも無ければ有効行とする、というロジックが最もスマートかな。

PatternCount() を使うなら
PatternCount( ¶ & $list_values & ¶ ; ¶ & $add_text & ¶ )
とされると、部分一致にも対応できます。

Last edited by Shin (2016-12-02 16:15:59)

Offline

#6 2016-12-02 16:20:39

Hiro
Member

Re: LetとEvaluateを使った再帰的な計算式について

文字列を一塊のValueにして、Value系関数で演算する作例。

Let(
[
   $start_tag="<img";   //タグ開始文字;
   $end_tag="/>";   //タグ終端文字;
   $start_attr="src=\"";   //属性開始文字;
   $end_attr="\"";   //属性終了文字;
   $sale_text=HTMLテキスト;
      $sale_text=Substitute($sale_text; [¶;""]);
         $sale_text=Substitute($sale_text; [$start_tag; ¶]);
   $saiki_kaisu=ValueCount($sale_text);
   $count=1;
   $list_values="";
   $saiki=
      "Case($count=$saiki_kaisu; $list_values;
         Let([
            $count=$count+1;
            $tag_text=GetValue($sale_text; $count);
               $tag_text=GetValue(Substitute($tag_text; [$end_tag;\"\¶\"]); 1);
            $attr_text=GetValue(Substitute($tag_text; [$start_attr;\"\¶\"]); 2);
               $attr_text=GetValue(Substitute($attr_text; [$end_attr;\"\¶\"]);1);
            $list_values=List($list_values; Case(FilterValues($list_values;$attr_text)=\"\"; $attr_text))
         ]; Evaluate($saiki))
      )"
];
   Evaluate($saiki)
)



【補足説明 追加】2016/12/2 18:45
・求める結果がValueListだから、やはりValue演算処理に持ち込むのが良さそうですネ。
・#1元式と比較し易いよう「$end_tag」タグ終端文字関連の以下2式を残していますが、
      こちらの式では省略してもロジック的に問題ありません。。
         /*$end_tag="/>";   //タグ終端文字;*/
         /*$tag_text=GetValue(Substitute($tag_text; [$end_tag;\"\¶\"]); 1);*/

Last edited by Hiro (2016-12-02 18:46:00)

Offline

#7 2016-12-02 19:17:10

tcf775
Member

Re: LetとEvaluateを使った再帰的な計算式について

Shin さん
Hiro さん

色々とご回答ありがとうございます。

確かに値一覧用の関数が用意されているんだから
それを使ったほうがいいですね ^^;

Hiroさんの作例は面白いですね!!
最初に繰返しの件数を数えておいて再帰内ではインクリメントするだけ。
そして対象の文字列を改行に置き換えていくことですべてGetValueで処理するとは....
このほうが、後で見たときにわかりやすいですね。


しかし、javascriptがタグ内に直書きされていたり、文書中でHTML文字がエスケープされていなかったり
とか可能性を考え始めるときりがないですね。


まだまだ勉強の必要があると感じました。
色々と検討いただきありがとうございました!!


実は…
正規表現が単体で使えたらいいなーとか思いながら作っていたのは秘密です。

Offline

#8 2016-12-03 12:41:15

Hiro
Member

Re: LetとEvaluateを使った再帰的な計算式について

終わってますが、1点補足しておきます。

Substituteは大小文字を区別するので、引数パラメータの書式統一処理が必須でしたね。

        $sale_text = Lower(HTMLテキスト);
        $start_tag = Lower(タグ開始文字);
        $end_tag = Lower(タグ終端文字);
        $start_attr = Lower(属性開始文字);
        $end_attr = Lower(属性終了文字);

Offline

#9 2016-12-04 17:17:29

Shin
Member

Re: LetとEvaluateを使った再帰的な計算式について

$sale_text=Substitute($sale_text; [¶;""]);
$sale_text=Substitute($sale_text; [$start_tag; ¶]);
この部分を、
$sale_text=Substitute($sale_text; [$start_tag ; ¶ & $start_tag];[$end_tag ; ¶ & $end_tag];[$start_attr ; ¶ & $start_attr];[$end_attr ; $end_attr & ¶]);
に変更すると、目的には、非常に見通しのいい文字列に変換できますよ。
ロジックとしては、頭の1行だけを見て、頭に$start_tagが見つかるまで行を削除していく。見つかれば、頭に$atart_attr が見つかるまで行を削除。頭に$end_tagが見つかれば、リセット。
見つかれば、その行の属性文字を外して別に保存、の繰り返しという単純な作業で済みます。

Offline

#10 2016-12-04 18:24:45

Hiro
Member

Re: LetとEvaluateを使った再帰的な計算式について

> Shinさん、その考え方も一案かと思いますが、再帰回数が一挙に4倍必要となり、
元々計算限界回数を極低く制限(約200回前後で限界)されたこの疑似的再帰式にとって、
根本的な意味の点では好まざる方向かなぁと......。

Last edited by Hiro (2016-12-04 18:29:09)

Offline

#11 2016-12-04 22:43:49

Shin
Member

Re: LetとEvaluateを使った再帰的な計算式について

確かに再帰は深くなってしまいますね。
ロジックを追いかけてみるには非常に良い構造になるので、取っ付きやすいと思います。また、$start_tag と $start_attr 合わせて100回程度まで対応できるので、実用的には十分かと思います。現場次第でしょう。

Last edited by Shin (2016-12-04 22:45:58)

Offline

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

Board footer

Powered by FluxBB
Modified by Visman

[ Generated in 0.005 seconds, 9 queries executed - Memory usage: 553.88 KiB (Peak: 574.42 KiB) ]