- ベストアンサー
配列の比較方法について
- 配列の比較方法について質問させてください。
- 複数のチェックボックスの値を取得し、別の配列と比較して一致項目の多い配列を決めたいです。
- 同数の場合、複数の配列を表示する方法について教えてください。
- みんなの回答 (1)
- 専門家の回答
質問者が選んだベストアンサー
照合結果を記録する配列変数 score_tbl は、選択するべき項目と一致した数( check_on フィールドの値)が”多い順に”並べ替えられます。 これは、先頭の要素である0番に、一致した数の最大値が配置されるということです。 従って、check_on フィールドの値が score_tbl[ 0 ].check_on と同じ値である要素を抜き出すと、一致した数が最も多かった要素を全て抜き出すことができます。 スクリプトの一例です。 (↓ 各行頭に全角のスペースが入っています。コピーする際は、全て半角のスペースかタブに置き換えてください) //*** /* 初期設定 */ //チェックボックスの選択状況を格納する配列 var check_status:Array = new Array(); //チェックパターンデータ //最後の要素はパターン名 var check_ptt:Array = [ [ 1 , 1 , 1 , 1 , 0 , 0 , 1 , 0 , 0 , "サンプルA" ] , [ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 1 , "サンプルB" ] , [ 0 , 1 , 1 , 0 , 0 , 0 , 1 , 1 , 0 , "サンプルC" ] ]; //評価を格納する配列 var score_tbl:Array = new Array(); //完全一致を検出する変数 //-1の時は完全一致なし、 //完全一致の時は配列のインデックス番号が入る var match:Number = -1; //チェックボックスの総数 var box_max:Number = 9; //チェックボタンが配置されているタイムラインを保持 var box_line:MovieClip = this; /* 照合の処理 */ function Check_Compare():Void { var i:Number , j:Number; var score:Number , check_score:Number; //完全一致を検出する変数をリセット match = -1; //選択状況とパターンを総当たりで照合する for( i = 0 ; i < check_ptt.length ; i++ ) { //評価をリセット score = 0; check_score = 0; //項目ごとのパターンと照合 for( j = 0 ; j < box_max ; j++ ) { //選択するべき項目との一致を照合 //両方とも1(選択されている)である場合、評価が+1、それ以外は加算されない check_score += check_ptt[ i ][ j ] & check_status[ j ]; //選択するべきではない項目も合わせた総合評価 //一致していた場合、評価が+1、それ以外は加算されない score += Number( check_ptt[ i ][ j ] == check_status[ j ] ); } //完全一致判定 //完全一致(=scoreが項目の総数と同じ)の場合、インデックスを記録する if( score == box_max ) { match = i; } //評価を記録する配列変数に結果を記録 //フィールド名 // ptt_ref:パターンへの参照 // check_on:選択するべき項目と一致した数 // total_score:総合評価 score_tbl[ i ] = { ptt_ref : check_ptt[ i ] , check_on : check_score , total_score : score }; } //完全に一致しているパターンがある場合は、それを出力 if( match != -1 ) { trace( "完全一致 : " + check_ptt[ match ][ box_max ] ) } //完全一致がない場合は、選択するべき項目が一致していた数が //多かったパターンをすべて抜き出す else { Judge(); } } /* 照合結果を評価する処理 */ function Judge():Void { var i:Number; var high:Number; var flags:Number; //照合結果を、評価の高い順に並べ替え //選択するべき項目と一致した数が多いものほど高評価 //同点の場合は総合評価で優劣を決める flags = Array.NUMERIC | Array.DESCENDING; score_tbl.sortOn( [ "check_on" , "total_score" ] , [ flags , flags ] ); //選択するべき項目が一致している数の最大を求める //最大値とは、配列変数の先頭に並んでいるcheck_onの値のこと high = score_tbl[ 0 ].check_on; //最大値と同じ一致数を持つパターンを抜き出す for( i = 0 ; score_tbl[ i ].check_on == high ; i++ ) { /*ここに、抜き出したパターンを 利用する処理を書く*/ trace( "パターン名 : " + score_tbl[ i ].ptt_ref[ box_max ] ); } } //*** 紙面の都合上、ボタンの処理を省略させていただきました。 スクリプトの解説です。 同じパターンがないものとすると、完全に一致する場合は1つしかないはずです。 完全一致は、検出するための変数を用意して考えます。上記のスクリプトでは match という変数です。 照合を始める前に、match の初期値を仮に -1 と決めます。 1つのパターンとの照合が終わった時点で、完全に一致していた場合は match にパターンのインデックス番号を入れます。 照合が全て終わった後、完全に一致したものがあれば match にはパターンの番号が入っていますが、なかった場合は、match は -1 のままです。 この点を利用して、match の値をもとに完全に一致したパターンを出力することができます。 完全に一致したものがない場合は、score_tbl の値を check_on フィールドに注目して並べ替え、最大値を持つ要素を全て抜き出します。 上記のスクリプトでは、Judge という関数内でこの処理を行います。 ActionScript の for ループは、2番目に記述した条件が成立している間、ループが継続する仕組みです。 if 文の機能を併せ持っているようなものですから、条件を工夫すると、単純に繰り返すだけでなく、様々な状況を判断しながら効率よく処理を進めることができます。 ループの条件を「 check_on フィールドの値が最大値と同じである間」と定めると、最大値と異なる check_on の値を持つ要素が出てくるまでループが継続します。 score_tbl の要素は check_on の値が大きい順に並ぶので、最大値を持つ要素は必ず連続して配置されます。 合わせますと、ループが継続している間は、i の値を利用して最大値を持つ要素だけを抜き出すことができます。 なお、No.7608367 では score_tbl の ptt_no フィールドにパターンの番号(配列変数 check_ptt のインデックス)を入れていましたが、今回は各要素の参照を入れて、score_tbl[ 番号 ].ptt_ref で該当するパターンを直接参照できるように変更してみました。 フィールドの名前や参照の方法が変わりましたので、ご注意ください。 ***** 前回も不明だったのですが。 一致している、というと、「選択するべきではない項目を”選択しなかった”」ことも正解といえるはずですが、これについてはどのように評価するのでしょうか? 完全一致以外の場合、「選択しなかった」ことによる正解数を評価する必要がないのでしたら、score_tbl に総合評価を記録する必要はなく、並べ替えも check_on フィールドにのみ注目して行うだけで済みます。
お礼
DPE様 ご返事大変遅くなってしまい申し訳ありません。 またまた今回も助けて頂き大変ありがとうございます。 ご教授頂きましたScriptで期待通りの動きができました。本当にありがとうございます! ご質問の件ですが、症状から病名を判定する仕組みを作ってまして、症状を絞りこんでいくと病名が判定できるということを希望しておりました。 けっか前回は説明不足で、またまた助けて頂きまして、本当に助かりました。Scriptの解説までもありがとうございます。ちゃんと勉強して理解できるようになりたいです。 取り急ぎお礼を書かせて頂きます。 ありがとうございましたm(__)m