2011-12-28 4 views
2

したがって、特定の条件が満たされたときに呼び出される関数を収集する場所を作成したいと思います。例えば。actionscriptの配列内の関数の収集と特定

function doSomething(someArg:Object):void { 
    if (conditionIsFalse){ 
     operationsToDoWhenConditionIsTrue.push(function(){ 
      doSomething(someArg); 
     }); 
    } 
} 

function onConditionBecomingTrue():void { 
    while (operationsToDoWhenConditionIsTrue.length > 0){ 
     operationsToDoWhenConditionIsTrue.shift()(); 
    }  
} 

これまでのところとても良いです。しかし、ある時点で、operationsToDoWhenConditionIsTrueを繰り返し、関数を識別して置き換えたいと思っています。 doSomethingのメソッド内の擬似コードでは、次のようになります。doSomethingのが2回呼び出された場合

function doSomething(someArg:Object):void { 
    if (conditionIsFalse){ 
     for (var i:int = 0; i<operationsToDoWhenConditionIsTrue; i++){ 
     // pseudo code here 
     if (typeof operationsToDoWhenConditionIsTrue[i] == doSomething){ 
      operationsToDoWhenConditionIsTrue[i] = doSomething(someArg); 
     } 
     } 
    } 
} 

は基本的に、私は唯一のoperationsToDoWhenConditionIsTrueが最新の呼び出しを保持します。明らかに、呼び出しはfunction(){}でラップされているので、すべての関数は同じです。私が欲しいものを達成できる方法はありますか?

+0

同一の操作を識別する基準は何ですか?操作は異なるdoSomething関数(つまり、それぞれの間に1-1のマッピング)で識別されますか? – outis

+0

うわー、私は今あなたのタイプコードを取り除くだけで、私の擬似コードは一種のものだと認識しています。 – pondermatic

答えて

1

同じものとして検出する操作を識別できる識別子関数を作成します。キューに追加する無名関数のプロパティとしてIDを割り当てます。キューを反復処理するときは、コレクションにIDを記録します。操作がすでにコレクション内にある場合は、その操作を実行しないでください。

function doSomething(someArg:Object):void { 
    if (conditionIsFalse){ 
     var operation = function(){ 
      doSomething(someArg); 
     }; 
     operation.operationID = objID(...); 
     operationsToDoWhenConditionIsTrue.push(operation); 
    } 
} 

function onConditionBecomingTrue():void { 
    var done = {}, f; 
    while (operationsToDoWhenConditionIsTrue.length > 0){ 
     f = operationsToDoWhenConditionIsTrue.shift(); 
     if (! f.operationID in done) { 
      done[f.operationID] = true; 
      f() 
     } 
    }  
} 

これより効率的な方法として、キューをIDでインデックス付けして、関数をキューに1回だけ追加できるようにします。ただし、操作が実行される順序を制御できなくなります。

var operationsToDoWhenConditionIsTrue:Object = {}; 

function doSomething(someArg:Object):void { 
    if (conditionIsFalse){ 
     operation.operationID = ...; 
     operationsToDoWhenConditionIsTrue[objID(...)] = function(){ 
      doSomething(someArg); 
     }; 
    } 
} 

function onConditionBecomingTrue():void { 
    for (id in operationsToDoWhenConditionIsTrue){ 
     operationsToDoWhenConditionIsTrue[id](); 
    } 
    operationsToDoWhenConditionIsTrue = {}; 
} 

あなたが順序を保持する必要がある場合(操作は順番に実行されるように、彼らが最初にキューに追加された、または順番に、彼らは最後に追加した)、その両方によってインデックス付けすることができますキュー・タイプを作成しますIDとシーケンスの間にマッピングを格納することによって実行できます。注:以下はテストされていません。

class OperationQueue { 
    protected var queue:Array = []; 
    protected var idToSeq:Object = {}; 

    public function push(op:Function):void { 
     /* Orders by last insertion. To order by first insertion, 
      simply return if the operation is already in the queue. 
     */ 
     if (op.id in this.idToSeq) { 
      var seq = this.idToSeq[op.id]; 
      delete this.queue[seq]; 
     } 
     this.queue.push(op); 
     this.idToSeq[op.id] = this.queue.length-1; 
    } 
    public function runAll():void { 
     var op; 
     while (this.queue.length > 0) { 
      if ((op = this.queue.shift())) { 
       delete this.idToSeq[op.id]; 
       op(); 
      } 
     } 
    } 
} 
+0

これのバリエーションをありがとう、ありがとう。私は、インデックスとしての関数と値としての引数を持つ配列を使用して終了しました。その後、呼び出す時間が来たとき、私はfunc.apply(this、args)を使用しました。これにより、operationIDが不要になりました。 – pondermatic

+0

オブジェクトのプロパティは整数または文字列でなければならないことに注意してください。関数を使用すると、最初に文字列に変換されます。これは、2つの異なる関数が同じ仮パラメータと本体を持つことはありそうもないので、まだ機能するはずです。代わりに[Dictionary](http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/utils/Dictionary.html)を使用して、オブジェクトをキーとして使用することもできます。 – outis

関連する問題