0

2 つのオブジェクトと式を取り、false ステートメントのフィルタリングを実行する API を開発しています。式が true と評価されるデータセットのみを持つ 3 番目のオブジェクトを返します。

var obj1 = [
        {cn: 101, name: "AA", seq:1},
        {cn: 106, name: "BB", seq:2}
    ];

var obj2 = [
        { cid: 100, name: "XX", locator: "r" },
        { cid: 101, name: "AA", locator: "p"},
        { cid: 507, name: "TT", locator: "r"}
    ];

var output = MyClass.filter(obj1, obj2, "{source.cn}==={target.cid}"); 

obj1 is source object
obj2 is target object

expected output is: 
output = [
         { cid: 101, name: "AA", locator: "p"}
     ];

私のクラスは汎用クラスであるため、任意の 2 つのオブジェクト (任意の構造と深さ) を受け入れ、任意の有効な JavaScript 式を実行できる必要があります。したがって、指定された式のパスを見つけて、式のリストを準備します。

source[0]["cn"]===target[0]["cid"]
source[0]["cn"]===target[1]["cid"]
source[0]["cn"]===target[2]["cid"]
source[1]["cn"]===target[0]["cid"]
source[1]["cn"]===target[1]["cid"]
source[1]["cn"]===target[2]["cid"]

式を取得したら、それぞれを評価し、間違ったものを除外します。

eval(source[0]["cn"]===target[0]["cid"]) >>>>>EVAL RESULT>>>>> false
eval(source[0]["cn"]===target[1]["cid"]) >>>>>EVAL RESULT>>>>> true 
eval(source[0]["cn"]===target[2]["cid"]) >>>>>EVAL RESULT>>>>> false 
eval(source[1]["cn"]===target[0]["cid"]) >>>>>EVAL RESULT>>>>> false 
eval(source[1]["cn"]===target[1]["cid"]) >>>>>EVAL RESULT>>>>> false 
eval(source[1]["cn"]===target[2]["cid"]) >>>>>EVAL RESULT>>>>> false 

これら 2 つのオブジェクトに obj1 100 の可能なパスと obj2 1000 の可能なパスが含まれている場合、myclass は 100,000 のステートメントを生成して評価します。それだけです。よく知られている評価が遅いために実行されますが、これらのステートメントは文字列であるため、「if」に入れることができません

if ステートメントでステートメントを使用したテスト コードを試してみましたが、非常に高速でした。if over eval を使いたいです。

私のテストコードは以下のとおりです。

var before = Date.now();
    var str, result, results = [], m, n;
    for(var i = 0, j=0; i <100000, j<100000; ++i,++j ){
        str = i + "===" + j;

        //eval(str)

        if(i === j) {
            result = true;
        } else {
            result = false;
        }           
    }

    var after = Date.now();
    console.log("Time: ", (after - before));

これらの式は任意の有効な JS 式である可能性があるため、演算子を想定することはできません。ユーザーは、式で任意の種類の演算子 (代入、比較、算術、ビット単位、論理、文字列、または特殊演算子) を自由に使用できます。

例えば ​​:

"{source.cn}==={target.cid} && {target.name} != 'XX'"
or
"({source.cn}==={target.cid} || {source.cn}/100 === 1 )&& {target.name} != 'XX'"
or anything else.

独自の式パーサーを書きたくありません。

(evalを使用せずに)提供することで助けてください3. 要件に妥協することなく高速化するためのその他のアプローチ (そして、ターゲット オブジェクトに複数の一致が存在する可能性があります)。

前もって感謝します。

4

1 に答える 1

3

そもそも eval はおそらく必要ありません。

文字列を渡すことから切り替えるだけです

var output = MyClass.filter(obj1, obj2, "{source.cn}==={target.cid}"); 

関数を使用するには

function comparator(source, target) { 
    return source.cn===target.cid 
}

var output = MyClass.filter(obj1, obj2, comparator); 

あなたのフィルターはとてもシンプルです!

function filter(array1,array2, comparator) {
  var ret = []
  array1.forEach(function(source) {
     array2.forEach(function(target) {
        if (comparator(source,target)) ret.push(source)
     }
  })

  return ret
}

もちろん、パフォーマンスが懸念される場合はArray.forEach、 simpleに置き換えforます。

于 2013-10-03T20:05:05.597 に答える