みんなに優しく、解りやすくをモットーに開設しています。 以下のルールを守りみんなで助け合いましょう。
1.ファイルメーカーで解らない事があればここで質問して下さい。 何方でも、ご質問・ご回答お願いします。 (優しく回答しましょう)
You are not logged in.
Pages: 1
いつも皆様にはお世話になっておりますm(__)m
Windows XP
filemaker Pro10
にて作業中
List関数にてリストにしたフィールドの情報をソートしたいのですが・・・
可能でしょうか?
カスタム関数あります。
http://www.briandunning.com/cf/290
カスタム関数あります。
http://www.briandunning.com/cf/290
ありがとうございますーーーーー!!!
うむ?
カスタム関数は標準版FMProでは利用できません。
そこで、標準関数だけで式を立ててみました。
ただ、リスト行数が最大290行位まで計算できますが、非常に重いので50行以下位しか実用にならない。^^;;
/*************************
リストのバブルソート計算式
**************************/
Let([
//パラメータ引数設定
$prm=リストフィールド;
$sor=1; //←(ソート条件指定:昇順=1,降順=0)
$typ=1; //←(ソートタイプ指定:テキスト比較=1,数値比較=0)
//サブルーチン関数定義
$lst=$prm;
$sub="Case(
$i<=1;$top;
Let([
$i=$i-1;
$itm=GetValue($lst;$i);
$_top=Case($typ;$top;$top*1);
$_itm=Case($typ;$itm;$itm*1);
$flg=Case($sor;$_top<$_itm;$_top>$_itm);
$rtn=Case($flg;List($rtn;$itm);List($rtn;$top));
$top=Case($flg;$top;$itm)
];Evaluate($sub))
)";
//バブルソート関数定義
$n=0;
$res="";
$fnc="Case(
$n=ValueCount($prm);$res;
Let([
$n=$n+1;
$i=ValueCount($lst);
$top=GetValue($lst;$i);
$rtn=\"\";
$res=List($res;Evaluate($sub));
$lst=$rtn
];Evaluate($fnc))
)"
];
Evaluate($fnc) //バブルソート計算実行
)
Last edited by Hiro (2013-09-20 20:02:07)
Offline
リスト内容を繰り返しに変換して、別テーブルからインポート。
そこでソートして全レコードコピーして別フィールドに貼り付けとか・・・
リストにした内容がテキスト、数字、日付によって面倒かも知れないけど。
Offline
チョ~鈍足のバブルソート再帰計算式に代わって、
「リスト内容が膨大」でかつ「高速ソート処理」を求める場合の代案です。
FMの自家スクリプト機能は脆弱なので、代わってWinOS標準装備のJScriptの
強力なソート機能で高速処理を実現・実装する案です。
データと結果のプログラム間受け渡しはクリップボードを経由させて楽してますが、
その分レスポンス時間のかなりの部分が掛かってしまっています。
●サンプル「フィールド内マスリストを高速ソート.fp7」→ http://yahoo.jp/box/MJynaF
(※WindowsOSに限定、fmp12はコンバートしてご覧下さい)
Offline
カスタム関数あります。
http://www.briandunning.com/cf/290
これは、よく見たら適当すぎて使えませんでした。
HIROさんのバブルソート計算式は、空値があると消去されますね。
プラグインなら、ScriptMasterに入ってました。これだと700行のソートが20msで終わります。テキストはUNICODE順になりますが。
最初のkaka wrote:WindowsXP filemaker Pro10 にて作業中
List関数にてリストにしたフィールドの情報をソートしたいのですが・・・可能でしょうか?・Hiroさんのバブルソート計算式は、空値があると消去されますね。
・プラグインなら、ScriptMasterに入ってました。これだと700行のソートが20msで終わります。テキストはUNICODE順になりますが。
・元々問い「List関数にてリストにしたフィールドの情報」に空行が含まれる余地はありませんけど?
もし、空行も含めたいケースなら、空行を適当なマーカ文字に退避させてからソート計算を行い、最後にマーカ文字を削除空欄に戻せば良いですネ。
・元々「WindowsXP」環境なので、特にプラグインなどを別途導入せずとも、標準機能だけでできるので先ずはその簡便法の事例サンプルを公開したのですが。^^;;
Last edited by Hiro (2013-09-24 16:42:19)
Offline
List ( 値 ; 値 )で、値が""の場合は消去されますけど、値が空行を含むリストの場合は消去されませんね。なんか微妙...
元々がList(関連テーブル::フィールド)なら、リレーションでソートすれば済むんですが。
「空行リストのソート」って果たしてどんな意義があるのかは置いといて、
一応、空行対応式は、
/*************************
リストのバブルソート計算式
**************************/
Let([
//パラメータ引数設定
$prm=リストフィールド;
$sor=1; //←(ソート条件指定:昇順=1,降順=0)
$typ=0; //←(ソートタイプ指定:テキスト比較=1,数値比較=0)
/**/
$dmy="_?_";
$prm=Substitute(¶&$prm&¶;"¶¶";¶&$dmy&¶);
$prm=Middle($prm;2;Length($prm)-2);
//サブルーチン関数定義
$lst=$prm;
$sub="Case(
$i<=1;$top;
Let([
$i=$i-1;
$itm=GetValue($lst;$i);
$_top=Case($top=$dmy;\"\";$typ;$top;$top*1);
$_itm=Case($itm=$dmy;\"\";$typ;$itm;$itm*1);
$flg=Case($sor;$_top<$_itm;$_top>$_itm);
$rtn=Case($flg;List($rtn;$itm);List($rtn;$top));
$top=Case($flg;$top;$itm)
];Evaluate($sub))
)";
//バブルソート関数定義
$n=0;
$res="";
$fnc="Case(
$n=ValueCount($prm);$res;
Let([
$n=$n+1;
$i=ValueCount($lst);
$top=GetValue($lst;$i);
$rtn=\"\";
$res=List($res;Evaluate($sub));
$lst=$rtn
];Evaluate($fnc))
)"
];
Substitute(Evaluate($fnc);$dmy;"") //バブルソート計算実行
)
Last edited by Hiro (2013-09-25 06:47:13)
Offline
最初のカスタム関数を使えないと言いましたけど、それっきり質問者が出てこないので、すでに解決なのかな。
数字とか英単語だけなら、あれでもできるんでしょうかね。
「ノームソート」というのが可愛げだったのでやってみたけど、値が20個ぐらいでも計算不可能だったりします。
(ループが1段な分すぐに再帰が深くなるので、この方法をカスタム関数にしても最悪220個=ルート5万ぐらいまでのようです)
Let ( [
$list = list ;
$n = ValueCount ( $list ) ;
$i = 1 ;
$f = "Case ( $i >= $n ; $list ;
Let ( [
$a = GetValue ( $list ; $i ) ;
$b = GetValue ( $list ; $i + 1 ) ;
$list = Case ( $a > $b ; LeftValues ( $list ; $i - 1 ) & $b & \¶ & $a & \¶ & RightValues ( $list ; $n - $i - 1 ) ; $list ) ;
$i = Case ( $a > $b and $i > 1 ; $i - 1 ; $i + 1 )
] ;
Evaluate ( $f )
)
)"
] ;
Evaluate ( $f )
)
毎回GetValueとかしないでちゃんと配列を作った方が速いかもしれない、とかいうレベルではなかった....
FM12で、作業用のテーブルsorter
n 数字 シリアル番号
v 非保存計算 GetValue($$list;n)
を作って、適当な数のレコードを入れておく。
Let ( [
$$list = list ;
n = ValueCount ( list )
] ;
ExecuteSQL ( "SELECT v FROM sorter WHERE n<=? ORDER BY v" ; "" ; "" ; n )
)
ノームソートを再帰でなくループでやってみました。
これなら400行まで可能(だけど時間は224行ループ回数23497の場合に10秒ぐらいかかってるので、実用性はあまりない)
Let([
$cond="$i<$n"; //While condition
$sort="Case($d[$i]>$d[$i+1];Let([$t=$d[$i];$d[$i]=$d[$i+1];$d[$i+1]=$t;$i=Max($i-1;1)];1);Let($i=$i+1;1))"; //action for a loop
$l=sort::list; //param for action
$split="Let([$i=$i+1;$d[$i]=GetValue($l;$i)];0)"; //make array
$join="Let([$i=$i+1;$r=$r&\¶&$d[$i]];1)";
$n=ValueCount($l);
//make loop for max 400 times
$f="If(" & $cond & ";Evaluate($do)+";
$g1=Substitute(10^400-1;9;"$f&");
$g=Evaluate(Left($g1;Length($g1)-1)) & "0" & Substitute(10^400-1;9;")");
$g2=Substitute($g;"$do";"$g");//400*400 times
$start=Get(UTCmSecs);
$i=0;
$do=$split;
$dummy=Evaluate($g); //make array
$i=1;
$do=$sort;
$dummy=Evaluate($g2); //sort
$i=0;
$r="";
$do=$join; //get result
];
//(Get(UTCmSecs)-$start) & "ms¶" &
Replace($r;1;1;"")
)
バブルソートの再帰計算を再帰ループスクリプトでやってみました。
この利点は、リスト行数の制限を受けずに、FMの標準機能だけで実装できる点です。
ただ、アルゴリズムが同じバブルソートなので時間が掛かる事は変わりません。
(リスト行数:15行→0秒、150行→3秒、750行→75秒、1500行→5分20秒)
・# パラメータ引数設定
・ 変数を設定 [$prm; 値:テーブル::リスト]
・ 変数を設定 [$sor; 値:1] //←(ソート条件指定:昇順=1,降順=0)
・ 変数を設定 [$typ; 値:1] //←(ソートタイプ指定:テキスト比較=1,数値比較=0)
・# 変数初期値設定
・ 変数を設定 [$lst; 値:$prm]
・ 変数を設定 [$n; 値:0]
・ 変数を設定 [$res; 値:""]
・# メイン ループ
・Loop
・ Exit Loop If [$n=ValueCount($prm)]
・ 変数を設定 [$n; 値:$n+1]
・ 変数を設定 [$i; 値:ValueCount($lst)]
・ 変数を設定 [$top; 値:GetValue($lst;$i)]
・ 変数を設定 [$rtn; 値:""]
・ # サブ ループ
・ Loop
・ Exit Loop If [$i<=1]
・ 変数を設定 [$i; 値:$i-1]
・ 変数を設定 [$itm; 値:GetValue($lst;$i)]
・ 変数を設定 [$_top; 値:Case($typ;$top;$top*1)]
・ 変数を設定 [$_itm; 値:Case($typ;$itm;$itm*1)]
・ 変数を設定 [$flg; 値:Case($sor;$_top<$_itm;$_top>$_itm)]
・ 変数を設定 [$rtn; 値:Case($flg;List($rtn;$itm);List($rtn;$top))]
・ 変数を設定 [$top; 値:Case($flg;$top;$itm)]
・ End Loop
・ 変数を設定 [$res; 値:List($res;$top)]
・ 変数を設定 [$lst; 値:$rtn]
・End Loop
・ フィールド設定 [テーブル::ソート結果; $res]
Last edited by Hiro (2018-05-17 19:53:03)
Offline
自レコードのみが関連レコードとなるリレーションを作り、
その動的値一覧をリストで作って、
ValueListItems
でそのリストを得ればソートされてますよね。
でいいのでは、、、
Offline
ああ、
同じ値が複数あると、一つになってしまいますね。。。
Offline
それと、「降順ソート」も「数値ソート」もできないので、
今回は論外ですね。
Offline
上の#14で、個別に設定していた変数設定ステップを
極力1つにまとめて、ステップ数を減らしたところ、
レスポンススピードが30%程向上できました。
// # パラメータ引数・変数の設定
・ 変数を設定 [$dmy; 値: Let([$prm=テーブル::リスト; $sor=1 /*(ソート条件指定:昇順=1,降順=0)*/; $typ=1 /*(ソートタイプ指定:テキスト比較=1,数値比較=0)*/; $lst=$prm; $n=0; $res="" ]; "")]
// # メイン ループ
・Loop
・ Exit Loop If [$n=ValueCount($prm)]
・ 変数を設定 [$dmy; 値: Let([$n=$n+1; $i=ValueCount($lst); $top=GetValue($lst;$i); $rtn=""]; "")]
// # サブ ループ
・ Loop
・ Exit Loop If [$i<=1]
・ 変数を設定 [$dmy; 値: Let([$i=$i-1; $itm=GetValue($lst;$i); $_top=Case($typ;$top;$top*1); $_itm=Case($typ;$itm;$itm*1); $flg=Case($sor;$_top<$_itm;$_top>$_itm); $rtn=Case($flg;List($rtn;$itm);List($rtn;$top)); $top=Case($flg;$top;$itm)]; "")]
・ End Loop
・ 変数を設定 [$dmy; 値: Let([$res=List($res;$top); $lst=$rtn ]; "")]
・End Loop
・ フィールド設定 [テーブル::ソート結果; $res]
Offline
Pages: 1
[ Generated in 0.006 seconds, 9 queries executed - Memory usage: 567.48 KiB (Peak: 588.39 KiB) ]