みんなに優しく、解りやすくをモットーに開設しています。 以下のルールを守りみんなで助け合いましょう。
1.ファイルメーカーで解らない事があればここで質問して下さい。 何方でも、ご質問・ご回答お願いします。 (優しく回答しましょう)
You are not logged in.
Pages: 1
いつもお世話になっております。javascriptでの計算結果(下記コード)の取得についてお伺いいたします。
最頻値と頻度を求める方法のコード
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset=utf-8 >
<title>Array_mode</title>
</head>
<body>
<script>
var store = ['aa','bb','cc','dd','ee','bb','ee','cc','ee','aa','bb'],
distribution = {},
max = 0,
result = [];
store.forEach(function (a) {
distribution[a] = (distribution[a] || 0) + 1;
if (distribution[a] > max) {
max = distribution[a];
result = [a];
return;
}
if (distribution[a] === max) {
result.push(a);
}
});
console.log('count: ' + max);
console.log('mode: ' + JSON.stringify(result));
//console.log(distribution);
</script>
</body>
</html>
webビューアでmapを表示してクリック座標の取得やchartjsで作ったグラフを画像として読み込む方法は、以前教えてもらった方法でなんとか出来るのですが、単純に上記のscriptをwebビューア内のdata:text/htmlに記述してその計算結果(最頻値と頻度)を別フィールドにFileMaker.PerformScriptWithOption ()で取得する方法では計算結果を取得出来ても無限loopの状態になる結果となります。
一寸古い紹介資料ですが・・・但し、内容は全く理解しておりません
https://notonlyfilemaker.com/2014/12/fi … on-engine/
にあるように計算用に別途jsファイルを用意してそこで計算を実行させその結果を取得するみたいな方法をとるしかないのでしょうか?
前回質問した最頻値を求めるための方法でjavascriptを利用できないかと思い考えていたのですが、どちらにしても配列用の変数として処理するだけでも時間がかかりあまり役に立たないと思っているところですが、日頃pythonよりjavascriptの方が計算速度が速いと聞いていましたしfilemakerとjavascriptの相性が非常に良いと喧伝されているので如何なものかと思いfilemakerから何らかの形でデータを渡しjavascriptで計算をしてその結果を取得するにはどうすれば良いのかご教授お願いします。
FileMakerのスクリプトでwv内の関数を叩いてその結果をまたFM側で受け取る?という事ですかね。
wvの中は
"data:text/html,
<!DOCTYPE html>
<html lang=\"ja\">
<head>
<meta charset=utf-8 >
<title>Array_mode</title>
</head>
<body>
<script>
var store = ['aa','bb','cc','dd','ee','bb','ee','cc','ee','aa','bb'];
function getMax() {
var distribution = {};
var max = 0;
var result = [];
var obj = {count: 0, mode: \"\"};
store.forEach(function (a) {
distribution[a] = (distribution[a] || 0) + 1;
if (distribution[a] > max) {
max = distribution[a];
result = [a];
return;
}
if (distribution[a] === max) {
result.push(a);
}
});
obj.count = max;
obj.mode = result;
console.log(obj);
FileMaker.PerformScript(\"script\", JSON.stringify(obj))
}</script>
</body>
</html>
"
として、storeを回す部分を関数getMaxで囲みます。この関数をFM側から叩くようにします。
(store以外の変数はgetMax関数内に移動させています。それと、結果をオブジェクトでまとめて渡すのでobjという変数を新たに作成しています。)
FMのスクリプトは2つ。
まず、getMax関数を叩くスクリプト、名前はなんでもいいので、こちらもgetMaxというスクリプト名にして、
webビューアでJavaScriptを実行[オブジェクト名: "web": 関数名;"getMax"]
とします。これを実行するとwv内のgetMax関数を叩けますので、
今度はこれを受け取るスクリプトここでは"script"と名付けます。
内容は
変数を設定$result : 値: Get(スクリプト引数)
で$resuletの中に戻り値が入ってきます。
上記の式だと
{"count":3, "mode":["ee","bb"]}
ですね。
storeの部分の配列もFileMakerから渡す場合は 、関数の上部を
function getMax(array) {
var store = JSON.parse(array);
に変更し、
webビューアでJavaScriptを実行[オブジェクト名: "web": 関数名;"getMax"; 引数: ここに配列を入れる]
でいけます。
FileMakerで配列を回す事と比較すると全然早いです。
Offline
calafate様 解答ありがとうございます。
コードをコピペし下記のスクリプトで実行したところ
Web ビューアで JavaScript を実行 [ オブジェクト名: "web"; 関数名: "getMax" ]
エラーメッセージ
スクリプトが見つかりません削除された可能性があります
が出ます。何が間違っているのか分かりませんが今度はjavascriptが動きません。
スクリプト名のタイプミスでした。お騒がせいたしました。
storeの部分の配列もFileMakerから渡す場合は、以前のバージョンで変数で渡すようにしていたのでfmのサンプル以外でも今回試してみます。
解決済ですが、
もしWindows環境であるなら、 最新「webビューア+javascript関数」手法を使わない方法もあります。
「mshta javascript: ~JS構文~ 」でjsを外部実行して、その結果はクリップボード経由で返す方法です。
この方法は、最新v19版でなくとも有効な手法となります。
Offline
Hiro様 クリップボード経由の方法の示唆有り難うございます。
今回の事は、前に質問した最頻値を求めるためのパフォーマンスの向上を図るための方法としてjavascriptを使えないか思ったからです。でも先にも記しましたが、そのためのfilemakerで配列を用意するために時間がかかる事からこの方法は半ば諦めております。で更なる方法としてfmからレコードをcsvデータとしてエクスポートしそれをjavascriptで配列に変換し(pythonなら直接csvファイルから計算できるが)そこから最頻値を求めることが出来ないかと思っています。次のコードが使えないかと試行している最中です。
function getCsv(url){
//CSVファイルを文字列で取得。
var txt = new XMLHttpRequest();
txt.open('get', "demo001.csv", false);
txt.send();
//改行ごとに配列化
var arr = txt.responseText.split('\n');
//1次元配列を2次元配列に変換
var res = [];
for(var i = 0; i < arr.length; i++){
//空白行が出てきた時点で終了
if(arr[i] == '') break;
//","ごとに配列化
res[i] = arr[i].split(',');
for(var i2 = 0; i2 < res[i].length; i2++){
//数字の場合は「"」を削除
if(res[i][i2].match(/\-?\d+(.\d+)?(e[\+\-]d+)?/)){
res[i][i2] = parseFloat(res[i][i2].replace('"', ''));
}
}
}
return res;
}
ここからは、最初の質問から外れ、もはやjavascriptの問題だと思いますが、一つに纏めることが出来るか?。または100万レコードから配列を素早く作成する方法があれば・・・
よろしくお願いいたします。
元データはFM内にあるようですが、配列にまとめるのが困難な感じでしょうか?
FMで改行区切りのリスト形式でwvのJSに渡して、そこで配列にすると楽なのではないでしょうか。上記JSも改行区切りを配列化されてますので。
さすがに100万レコードを一気に配列化はきついでしょうが。
Offline
calafate様 ありがとうございます。
さすがに100万レコードを一気に配列化はきついでしょうが。
ですか!・・・この方法放棄します。
FMで改行区切りのリスト形式でwvのJSに渡して、そこで配列にすると楽なのではないでしょうか。
試行した方法、配列をloopで作成したところ10万レコードで正確ではないが10秒近くかかりました。よってもっと素早い方法は?
とりあえず
そういえば、速度ということならxDBC共有を設定してJavaでアクセスするのが一番早いという話を(数年前ですが)英語コミュニティで見たのを思い出しました。
エクスポートするのでは、それ自体が時間を食うでしょう。
himadanee様
csvファイルにエクスポートすること自体は100万レコードで私のpcで3秒から4秒ぐらいだったと思います。pythonで求めた場合スクリプトの停止時間2秒を入れても5から6秒の間で計算結果をインポートできたのですから
xDBC共有を設定してJavaでアクセスするのが一番早いという話を
ODBCで直接fmのレコードにjavascriptでアクセス可能とのことでしょうか
himadanee様 タグ設定の方法がよく分からないので発言者名を間違えていました。申し訳ありません。
パフォーマンス問題が主題なら、FM内解法での高速化をもう一度検討し直してみても良いかも?
Offline
Hiro様 決して主題はパフォーマンス問題ではありません。私の質問である、javascriptの計算結果の取得に関しては解決済みですので申し訳ありません。余計な質問を積み重ねて・・・
100万レコードで配列を作成しフィールドに配置、その値を変数にしてvar storeの配列に渡し実行したところ「スタックオーバーフローが発生しました:1」が出て終わりでした。10万レコードでは問題がなかったのに!2938643ミリ秒をかけ配列を作成したのに。htmlで配列に貼り付けて実行しても問題なくちゃんと最頻値が出る。webビューアだと駄目なのか?
以上で解決とします。
あまり役に立たない訂正です。前回
100万レコードで配列を作成しフィールドに配置、その値を変数にしてvar storeの配列に渡し実行したところ「スタックオーバーフローが発生しました:1」が出て終わりでした。
の結果になりましたが、あるサイトに
JavaScript関数に渡すことができるデータの量に制限はありません。
とありましたので、今回は、calafateさんの勧められていた
storeの部分の配列もFileMakerから渡す場合は 、関数の上部を
function getMax(array) {
var store = JSON.parse(array);
を使ってみました。100万レコードの配列を別フィールドに準備してから実行したところ私のwindows10 PCで5444ミリ秒でした。前回の後、直接wvに書き込める文字数の制限がに中ったり、list()を使った全置換えでは改行リストまでは出来るのですが配列に変換できない限度があるのか?)などいろいろありまして、今回は、無難にcsvデータをエディタで読み込み改行を置き換える等の手作業で配列を準備しFMにコピペしました。
もう一つ忘れていた。Microsoft Edgeでjavascriptを実行したところ220~330ミリ秒でした。やはりpytonより速い!
前レスの誤字脱字につき申し訳ありませんでした。
fmの動作がよく分からないが、スクリプトやフィールド値など編集してからの処理速度の計測値よりそのファイルを一度閉じ再度開いたときの方が速いし新しくスクリプトを書いても前のスクリプトの処理速度が遅くなったり? なお、前回の値が5444ミリ秒に対し2000ミリ秒台になっています。
今回は、100万レコードから配列を作る方法としてExecuteSQL()を使ってみました。
引数をフィールド値から下記の計算式に変更
"[\"" & ExecuteSQL ( "select \"item\" from \"data\" ";"";"\"" & "," & "\"") & "\"]"
計測値は、作成に掛かる時間を加えても5回平均で5650ミリ秒でした。ExecuteSQL()は余計なSQLを走らせないと結構使えることが分かっただけでも勉強になりました。
Pages: 1
[ Generated in 0.013 seconds, 9 queries executed - Memory usage: 566.96 KiB (Peak: 587.87 KiB) ]