2011-01-12 7 views
8

JavaScriptの専門家の実装の詳細は次のとおりです。JavaScriptで複雑なデシジョンテーブルを実装する

私は、フィールドの値は、入力の7ビットの値に複雑に依存しているフィールドの数とUIを持っています。ユーザがアプリケーションの多くを見て、常に変化している可能性のある128の値のどれに表示されるべきでしょうか?

今、私がされたif-then-elseくして決定木として実装され、このためにきましたが、それは権利を取得するのは難しいの要件の変更や並べ替えの下に脆いです。

は私が考えた

一の実施のアプローチは、から0x7Fには0x0の値の配列を作成し、各位置での閉鎖を格納することである -

var tbl; // initialize it with the values 
    ... 
tbl[0x42] = function(){ doAThing(); doAnotherThing(); } 

、その後でそれらを呼び出す

tbl[bitsIn](); 

これは、少なくとも決定ロジックを一連の割り当てにします。

質問:良い方法がありますか?

(更新:?。神聖ながらくた、how'd 'AJAX iphoneタグ' について、その行がそこに入るのも不思議はそれが少し不可解だった)

更新

だから何が起こりました?基本的に私は第4の選択肢を取ったが、私がチェックしたものと似ていた。論理は十分に複雑で、私は最終的にサーバで真理値表を生成するPythonプログラムを作成しました(実際にはGroovyコードを生成し、ホストはGrailsアプリケーションです)、決定ロジックをサーバに完全に移動します。 JavaScript側では、さまざまなフィールドの値を含むJSONオブジェクトを単純に解釈します。

結局、これはおそらく1回の以上の繰り返しを通過し、ビットのベクトルでインデックス化するデータベーステーブル内のデータを、となります。

テーブル駆動部分が確かに出てきています。既に表示されている特定の要件が変更されています。の変更があります。

+2

を、あなたのリファクタリングの考えは健全であるが、TBH Iあなたの説明から、あなたが必要としていることは分かりません:P –

+0

各ビットは特定のアクションを決定しますか?もしそうなら、なぜ[0x01、0x02、0x04、0x08、0x10、0x20、0x40]に対して値をビット単位でANDしないでください。 – draeton

+0

@Martin、ポイントは、これは私のテーブルよりも柔軟な方法ですラムダの –

答えて

1

意思決定ツリーを手作業で書くのではなく、サーバー上で生成すると考えましたか?どのような表現でもクリーンで作業が簡単で、変更してコンパイルすると、クライアント側にとっては醜いしかし効率的なJavaScriptになります。

意思決定ツリーは、データとして表現するのがかなり容易であり、伝統的なツリーデータ構造として理解して扱いやすくなります。あなたはどのような形式であれ、あなたに合ったツリーを保存することができます。それをデータとして検証し修正することもまた真剣に行われるはずです。

デシジョンツリーを使用する必要がある場合は、それをJavaScriptにコンパイル/シリアル化するだけで、大規模なif-the-else、switch、またはハッシュ混乱を招くことがあります。これはまたかなり平直で、数百の要素でswitchを維持しようとするよりもずっと簡単です。

2

状況が(あなたが説明したように)非常に不規則なので、より良い方法ではないようです。しかし、私はあなたのジャンプテーブルの改善を提案することができます。エラーと重複があると述べました。したがって、明示的にクロージャーに割り当てる代わりに、明示的なクロージャーを複製する必要がないように、それらを名前付き関数に割り当てることができます。

var doAThingAndAnother = function(){ doAThing(); doAnotherThing(); } 

var tbl; // initialize it with the values 
    ... 
tbl[0x42] = doAThingAndAnother; 
tbl[0x43] = doAThingAndAnother; 

それほど多くの改善はありませんが、それは私が考えることができる唯一のものです!あなたは他の問題のほとんどをカバーしたようです。要件がそんなに変わったように見えるので、優雅さを忘れて、エレガントではないデザインを変えなければならないかもしれないと思う。

5

2つのオプションがあります...両方のソリューションに共通

次の名前付き関数は以下のとおりです。

function aThing() {} 
function anotherThing() {} 
function aThirdThing() {} 

スイッチ道

function exec(bits) { 
switch(bits) { 
    case 0x00: aThing(); anotherThing(); break; 
    case 0x01: aThing(); anotherThing(); aThirdThing(); break; 
    case 0x02: aThing(); aThirdThing(); break; 
    case 0x03: anotherThing(); aThirdThing(); break; 
    ... 
    case 0x42: aThirdThing(); break; 
    ... 
    case 0x7f: ... break; 
    default: throw 'There is only 128 options :P'; 
    } 
} 

あなたが

を呼びたいの両方のケースでは、マップ方法

function exec(bits) { 
    var actions = map[bits]; 
    for(var i=0, action; action=actions[i]; i++) 
     action(); 
} 

var map = { 
0x00: [aThing, anotherThing], 
0x01: [aThing, anotherThing, aThirdThing], 
0x02: [aThing, aThirdThing], 
0x03: [anotherThing, aThirdThing], 
    ... 
0x42: [aThirdThing], 
    ... 
}; 

exec(0x42); 
+0

そのループは 'for(アクションのvarアクション)action();'にできませんでしたか? –

+0

それはほとんど意味をなさないだろう。この場合のアクションは関数参照の配列であり、for(var i in array)を使用して配列をループするのはずっと遅く、ブラウザ間で結果が不均一になるためです。一部のブラウザでは、配列の「長さ」プロパティをオブジェクトの別のメンバーとして扱い、関数参照と同様にそれを渡します。 –

+0

[] .propertyIsEnumerable( 'length')=== false – draeton

1

私はあなたが見て取りたい場合はJavaScript決定木ツールのラフな例を持っている:私はあなたの問題を理解して何から

http://jsfiddle.net/danw/h8CFe/

関連する問題