🧙
FileMaker 改行区切りリストから、行検索
「行抜きカスタム関数スピードコンテスト」の時に作ったヤツの解説。
ヒット数が多くてもそれなりのスピードで実行できます。
下記の例は、数行ですが、スピードコンテストのときは、4,000行くらい...
「1」を検索と言うお題が追加され、全行ヒットすると言う事に...
LOOPでは、遅くなるので、なんとかしてLOOP無しで出来ないかと考えたのが今回の計算式です。
対象
1017621|アースエコロコ
1002616|メイドインアース
1012036|アース製薬
1023218|ジル バイ ジルスチュアート
1000774|ジルスチュアート
1024198|シェアースピリット
1001659|アースミュージック
1022279|アークスタンダード
1024062|リムアーク
1001657|アークテリクス
検索ワード
アース
Let([
~val = 行抜きカスタム関数の話::検索ワード
;~str = 行抜きカスタム関数の話::対象
;~char182 = "{c;h:a;r:1;8:2}"
;~str =Substitute ( ~str ; Char ( 182 ) ; ~char182 )
;~str = Quote ( ~str )
;~str = Middle ( ~str ; 2 ; Length ( ~str )-2)
;~formula =
"LET(~val=\"" & ~val & "\";" &
"LET(~str=\""
&
Substitute ( ~str ; Char ( 182 ) ;
"\";if(PatternCount(~str; ~val );~str & Char( 13 ))) & ¶LET(~str=\""
)
&
"\";if(PatternCount(~str ; ~val );~str))"
& ")"
;~result = Substitute ( Evaluate ( ~formula ) ; ~char182 ; Char ( 182 ))
];
~result
)
改行マーク対策
対象に「¶」があるとエラーになるので、"{c;h:a;r:1;8:2}" に置換
;~char182 = "{c;h:a;r:1;8:2}"
;~str =Substitute ( ~str ; Char ( 182 ) ; ~char182 )
Quote を適用し前後の「"」を削除
計算式内に挿入するため
;~str = Quote ( ~str )
;~str = Middle ( ~str ; 2 ; Length ( ~str )-2)
元の文章の改行を計算式に置換
Quote を適用しているので実際には、 Char ( 182 ) を置換
;~formula =
"LET(~val=\"" & ~val & "\";" &
"LET(~str=\""
&
Substitute ( ~str ; Char ( 182 ) ;
"\";if(PatternCount(~str; ~val );~str & Char( 13 ))) & ¶LET(~str=\""
)
&
"\";if(PatternCount(~str ; ~val );~str))"
& ")"
~formula は、以下のようなFileMakerの計算式になります。
~formula
LET(~val="アース";
LET(~str="1017621|アースエコロコ";if(PatternCount(~str; ~val );~str & Char( 13 ))) &
LET(~str="1002616|メイドインアース";if(PatternCount(~str; ~val );~str & Char( 13 ))) &
LET(~str="1012036|アース製薬";if(PatternCount(~str; ~val );~str & Char( 13 ))) &
LET(~str="1023218|ジル バイ ジルスチュアート";if(PatternCount(~str; ~val );~str & Char( 13 ))) &
LET(~str="1000774|ジルスチュアート";if(PatternCount(~str; ~val );~str & Char( 13 ))) &
LET(~str="1024198|シェアースピリット";if(PatternCount(~str; ~val );~str & Char( 13 ))) &
LET(~str="1001659|アースミュージック";if(PatternCount(~str; ~val );~str & Char( 13 ))) &
LET(~str="1022279|アークスタンダード";if(PatternCount(~str; ~val );~str & Char( 13 ))) &
LET(~str="1024062|リムアーク";if(PatternCount(~str; ~val );~str & Char( 13 ))) &
LET(~str="1001657|アークテリクス";if(PatternCount(~str ; ~val );~str))
)
上記式の1行抜粋
行ごとに PatternCount で判定
LET(
~str="1017621|アースエコロコ"
;
if(PatternCount(~str; ~val );~str & Char( 13 ))
) &
Evaluate で計算式を実行
Evaluate で計算式を実行し、~char182 を Char ( 182 ) へ置換
※ Char ( 182 ) = ¶
;~result = Substitute ( Evaluate ( ~formula ) ; ~char182 ; Char ( 182 ))
文字数が多い場合の対応
4千行、30万文字くらいは、上記の式で問題ありません。
が、文字数が多くなるとエラーになります。(何文字でエラーになるかは未調査)
& より、Listで連結したほうがチョット速いのでListで連結と、
文字数が多い場合の対応で、1,000行づつ処理を行う式
Let([
~str = ¶ & textToFilter & ¶
;~val = searchValue
;~pCount = PatternCount ( ~str ; ~val )
;~p = Position ( ~str ; ~val ; 1 ; ~pCount )
;~e = Position ( ~str ; ¶ ; ~p ; 1 )
;~p = Position ( ~str ; ~val ; 1 ; 1 )
;~s = Position (Left ( ~str ; ~p ) ; ¶ ; ~p ; -1) + 1
;~str = Middle ( ~str ; ~s ; ~e - ~s+1 )
];
While (
[
~count = ValueCount ( ~str )
;~n = 0
;~x = 1000
;~max = Ceiling ( ~count/~x )
;~result = ""
] ;
~n < ~max ;
[
~str1 = MiddleValues ( ~str ; (~x*~n)+1 ; ~x )
;~str1 = Replace ( ~str1 ; Length ( ~str1 ) ; 1 ; "" )
;~result = List( ~result ;
Let([
_val = ~val
;_str = ~str1 & If ( PatternCount ( ~str1 ; ¶ ) = 0 ; ¶ )
;_char182 = "{c;h:a;r:1;8:2}"
;_str =Substitute ( _str ; Char ( 182 ) ; _char182 )
;_str = Quote ( _str )
;_str = Middle ( _str ; 2 ; Length ( _str )-2)
;_formula =
"LET(_val=\"" & _val & "\";" &
"¶list(¶LET(_str=\""
&
Substitute ( _str ; Char ( 182 ) ;
"\";if(PatternCount(_str; _val );_str));¶LET(_str=\""
)
&
"\";if(PatternCount(_str ; _val );_str))"
& "¶)¶)"
;_result = Substitute ( Evaluate ( _formula ) ; _char182 ; Char ( 182 ))
];
_result
)
)
;~n = ~n+1
] ;
~result
)
)
カスタム関数:
Discussion