0

キューから重複するエントリを効率的に削除したいと思います。キューには、DateTimeとFullPathおよびその他のいくつかのカスタムクラスがあります

private Queue<MyCustomClass> SharedQueue;

クラスのDateTimeは、キューに挿入されたときのタイムスタンプです。使用したいロジックは次のとおりです。FullPathが4秒のウィンドウ内で同一である場合(つまり、重複するフルパスから4秒以内にキューに追加された場合)、キューから重複を削除します。見たいイベントがありますが、まだいくつかの複製が届きますので、問題ありません。

私はc#2.0とFileSystemWatcherクラスとワーカーキューを使用しています。

これを行うには、さまざまな方法があります。アイテムが追加されるたびにキューをトリミングするか、キューで作業しているときに、現在の重複アイテムの処理をスキップします。

または、「グローバルプライベート」変数Dictionary <String、DateTime>を使用する必要がありますか?だから私はすぐにそれを検索できますか?またはキューのローカルコピー?多くのファイルイベントが発生する場合は、ローカルキューを100アイテムに制限するのが最善でしょうか。私の場合、フォルダ内で監視するファイルは比較的少ないはずですが...しかし、状況は常に変化します...

助けてくれてありがとう。

:編集:2月10日8:54 EST:それで、私が知る限り、良い単純なソリューションを実装することにしました。Dictキーを長く保持しすぎているとは思いません...

:編集:2月10日9:53 EST:辞書に重複する値を含めることができないため更新されました。

   public void QueueInput(HotSynchUnit.RcdFSWFile rcd)
// start the worker thread when program starts.
// call Terminate.Set() in the programs exit routine or close handler etc.
{
  // lock shared queue
  lock (SharedQueue)
  {
    if (!IsDuplicateQueueInput(rcd))  // only add unique values to queue
    {
      SharedQueue.Enqueue(rcd);
      SomethingToDo.Set();
    }
  }
} // public void QueueInput

private bool IsDuplicateQueueInput(HotSynchUnit.RcdFSWFile rcd)
/* Return true if the object is a duplicate object.
 * Pseudo Code:
 * 
 * isDuplicate = false
 * Lock Dictionary
 * -If lastTimeStamp > 4 seconds ago then       // Optimization: save lastTimeStamp
 *    if Dict.Count > 0 then clear Dictionary
 *    return isDuplicate
 * -If not Dict.TryGetValue(sPath, dtTimeStamp) then
 *    Dict.AddKey()
 * -Else
 *    Compare key timestamp to Currenttime
 *    if key timestamp is <= 4 seconds ago then
 *       IsDuplicate = True
 *
 *    Dict.RemoveKey()
 *    Dict.AddKey()
 * 
 * return isDuplicate
*/
{
  // put real code here
}
4

4 に答える 4

1

一般的なハッシュテーブルに似たコレクションを使用することを考えました...次のようなものです。

Dictionary<string, YourClass> dict = new Dictionary<string, YourClass>();

/// just let's assume you want to add/check for "c:\demo.txt"

if (!dict.ContainsKey(@"c:\demo.txt"))
{
   /// add items to dict by passing fullPath as key and your objects as value
   dict.add(@"c:\demo.txt", obj1);
} 
else if (dict[@"c:\demo.txt"].CheckForIntervall())
{
   /// replace current object in dictionary with new object - in case you want to..
   /// or just do what you want to 
}

編集-カスタムクラスには、次のような機能が含まれている場合があります。

class YOURCUSTOMCLASS
{
    private DateTime creationTime;

    public DateTime CreationTime
    { get { return creationTime; } }

    public YOURCUSTOMCLASS(parametersGoesHere xyz)
    {
          creationTime = DateTime.Now;
    }

    /// in this case this method will return true
    /// if the timeSpan between this object and otherObject
    /// is greater than 4 seconds
    public bool CheckForInterval(YOURCUSTOMCLASS otherObject)
    {
         TimeSpan diff = otherObj.CreationTime.Subtract(creationTime);

         /// you may replace 4 through any other digit, or even better take
         /// a const/global var/static ...
         return diff.TotalSeconds > 4;
    }

    /// all the other stuff you need ...
}

もちろん、キューの機能は失われますが、キューに多くの要素が含まれていると、実行時間が大幅に増加します。

hth

于 2011-02-09T17:34:45.440 に答える
0

私はサブクラスを作ります:

class MyDeduplicatedQueue : Queue<MyCustomObject> {
    /// etc
}

次に、適切なフィルタリングロジックをすべてEnqueueメソッドに組み込むことができます。

于 2011-02-09T16:50:36.623 に答える
0

基本型Queueのユーザーは異なる動作を期待するため、ラッパークラスを作成し、キューから拡張しません。(.NET 4.0のデータコントラクトは、そうすると文句を言うことさえあります。)

内部的には、必要な呼び出しをリダイレクトする実際のキューを持つことができます。Queue()を呼び出すたびに、新しい要素がまだ含まれていない場合は、辞書に追加できます。そうする前に、このディクショナリからx秒より古いすべての要素を空にして、それらを順番に内部キューに追加することができます。

デキューするときは、内部キューに要素が含まれているかどうかを確認する必要があります。そうでない場合は、ディクショナリから最も古い要素を選択します。

もちろん、これは可能な実装の1つにすぎません。多くの異なる要素がすぐにキューに入れられる可能性がある場合、ディクショナリはすぐにいっぱいになり、それを解決するために追加のロジックを追加する必要がある場合があります。

于 2011-02-09T17:28:19.767 に答える
0

パスが重複している場合、挿入を拒否しないのはなぜですか?あなたがしなければならないのは、キューの末尾から開始し、重複を見つけたとき(そして挿入を拒否したとき)またはタイムスタンプが制限時間を超えたとき(そしてレコードを挿入したとき)に停止する線形検索です。別のデータ構造とそれに関連するすべてのロジックを保持するよりもはるかに簡単なようです。

于 2011-02-09T17:50:38.007 に答える