プロが教えるわが家の防犯対策術!

以前ActionScriptの配列の比較で一度ご質問させて頂き解決(DPE様へご教授頂き)したのですが、その後改良しまた問題が出てきてしまいました。

複数のチェックボックスの値(true,false)を取得して配列に格納し、別の配列(A、B、C)と比較をし一致項目の多い配列を決める処理で
「全てのチェックボックスの選択状況を集めたデータを作り、同じ数のデータ同士で比較」という方法をご教授頂き参考のScriptまで書いて頂いたのですが
http://oshiete.goo.ne.jp/qa/7608367.html

例として・・・・
・チェックボックスが9個あり
・それぞれ、1~9まで任意の名前がついております。
・チェックされた値を取得し
アンサー配列[2,3,4]を作った場合

一致項目が多いもの
A配列[1,2,3,4,7,"サンプルA"] この場合3個同じ
B配列[1,2,3,4,5,6,7,9,"サンプルB"] この場合3個同じ
C配列[2,3,7,8,"サンプルC"] この場合2個同じ

現状同数の場合、A配列「サンプルA」が表示されます。
1つのみ表示をさせているんですが、最大の数で同数の場合(3が一致項目が多い)、複数表示という仕組みに切り替えたいと四苦八苦しておりました・・・(T_T)
結果的に「サンプルA、サンプルB」というように表示させたいのです。
※完全一致なら表示されるのは1つだけになります。

解決済みの問題を再度掘り返すようで大変申し訳ありませんが、どなたかご教授頂ければとおもいます。よろしくお願いたします。

説明が上手くできてなくて、意味不明や、何か問題などございましたらすぐに対応させて頂きますのでご連絡頂ければとおもいます。


※DPE様にご教授頂きましたScriptを若干変更し現在利用しております。

現在のScript
//***

/*
 初期設定
*/

//チェックボックスの選択状況を格納する配列
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 , 0 , 1 , 0 , 1 , "サンプルB" ] ,
[ 0 , 1 , 1 , 0 , 0 , 0 , 1 , 1 , 0 , "サンプルC" ]
];

//評価を格納する配列
var score_tbl:Array = new Array();

//チェックボックスの総数
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;
 var flags:Number;


 //選択状況とパターンを総当たりで照合する
 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 ] );
  }

  //デバッグ
  trace( "Score " + i + " = " + score );
  trace( "Check_on " + i + " = " + check_score );

  //評価を記録する配列変数に結果を記録
  //フィールド名
  // ptt_no:パターンの番号
  // check_on:選択するべき項目と一致した数
  // total_score:総合評価
  score_tbl[ i ] = { ptt_no : i , check_on : check_score , total_score : score };
 }

 //評価の高い順に並べ替え
 //選択するべき項目と一致した数が多いものほど高評価
 //同点の場合は総合評価で優劣を決める
 flags = Array.NUMERIC | Array.DESCENDING;
 score_tbl.sortOn( [ "check_on" , "total_score" ] , [ flags , flags ] );

 /*ここに、評価を利用する処理を書く*/
 /*今回は一致した数が最も多かったパターンの名前を出力*/
 /*ダイナミックテキストに出力*/
 t1 = check_ptt[ score_tbl[ 0 ].ptt_no ][ box_max ] );
}


/*
 照合開始ボタンの処理
*/

btn.onRelease = function():Void
{
 var i:Number;


 //選択状況を配列変数に格納
 //選択されている場合1、されていない場合は0を入れる
 for( i = 0 ; i < box_max ; i++ )
 {
  check_status[ i ] = Number( box_line[ "cbox" + i ].selected );
 }

 //パターンと照合する
 Check_Compare();
};


//***

A 回答 (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 フィールドにのみ注目して行うだけで済みます。
    • good
    • 0
この回答へのお礼

DPE様 ご返事大変遅くなってしまい申し訳ありません。
またまた今回も助けて頂き大変ありがとうございます。

ご教授頂きましたScriptで期待通りの動きができました。本当にありがとうございます!

ご質問の件ですが、症状から病名を判定する仕組みを作ってまして、症状を絞りこんでいくと病名が判定できるということを希望しておりました。

けっか前回は説明不足で、またまた助けて頂きまして、本当に助かりました。Scriptの解説までもありがとうございます。ちゃんと勉強して理解できるようになりたいです。

取り急ぎお礼を書かせて頂きます。
ありがとうございましたm(__)m

お礼日時:2012/11/19 18:20

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!