3

に大量のファイル名がありmy_dir/my_subdir、何らかの方法でフォーマットされているとします。

data11_7TeV.00179691.physics_Egamma.merge.NTUP_PHOTON.f360_m796_p541_tid319627_00
data11_7TeV.00180400.physics_Egamma.merge.NTUP_PHOTON.f369_m812_p541_tid334757_00
data11_7TeV.00178109.physics_Egamma.merge.D2AOD_DIPHO.f351_m765_p539_p540_tid312017_00

たとえばdata11_7TeV、実行番号、data_typeデータ形式です。00179691NTUP_PHOTON

私はこのようなことをするためのインターフェースを書きたいです:

dataset = DataManager("my_dir/my_subdir").filter_type("data11_7TeV").filter_run("> 00179691").filter_tag("m = 796");                     
// don't to the filtering, be lazy
cout << dataset.count();                          // count is an action, do the filtering
vector<string> dataset_list = dataset.get_list(); // don't repeat the filtering
dataset.save_filter("file.txt", "ALIAS");         // save the filter (not the filenames), for example save the regex
dataset2 = DataManagerAlias("file.txt", "ALIAS"); // get the saved filter
cout << dataset2.filter_tag("p = 123").count();

countたとえば、やのようなアクションの前に実際のフィルタリングを行う必要はありませんget_list。フィルタリングが既に行われている場合、フィルタリングをやり直したくありません。私はちょうどデザインパターンについて何かを学んでいて、私が使うことができると思います:

  • メソッドAbstractFilterを実装する抽象基本クラスfilter*
  • 呼び出されたメソッドからデコレータが使用するものを決定するファクトリ
  • filter* メソッドを呼び出すたびに、装飾されたクラスを返します。次に例を示します。

AbstractFilter::filter_run(string arg) {
    decorator = factory.get_decorator_run(arg);  // if arg is "> 00179691" returns FilterRunGreater(00179691)
    return decorator(this);
}

  • ファイル名をフィルタリングするために正規表現を構築するが、フィルタリングを行わないプロキシ

私はjQueryも学んでおり、同様の連鎖メカニズムを使用しています。

誰かが私にいくつかのヒントを教えてもらえますか? このようなデザインが説明されている場所はありますか?特にファイル名の新しい形式を処理するために、設計は非常に柔軟でなければなりません。

4

4 に答える 4

3

デザインパターンの側面を過度に複雑にし、根底にあるマッチング/インデックス作成の問題をごまかしていると思います。ディスクから完全なディレクトリ リストを取得することは、それが返すファイル名を RAM 内でフィルタリングするよりも桁違いにコストがかかることが予想されますcount()。に対するいくつかの遅延イテレータ操作)。get_list()datasetdataset

提示されているように、実際の機能上の課題は、ファイル名のインデックスを作成することであり、一致するファイルを繰り返しすばやく見つけることができます。ただし、おそらくファイル名のデータセットを取得してから実際にそれらのファイルを開くまでに進むと思われるため、それもありそうにありません。これもまた桁違いに遅くなります。したがって、索引付けを最適化しても、プログラム全体のパフォーマンスに大きな影響を与えることはありません。

しかし、一致するすべてのディレクトリ エントリを配列 A に読み込むとします。

さて、フィルタリングのために、あなたの要件は一般的に と を使用して満たすことができるstd::multimap find()ようlower_bound()ですupper_bound()。これにアプローチする最も一般的な方法は、A のインデックスのリストにマップするデータ型、実行番号、データ形式、p値、m値などに個別のマルチマップを用意することです。その後、既存の STL アルゴリズムを使用して、そのインデックスを見つけることができます。tid個々のフィルターの結果に共通です。

データとフィルタリングのニーズに関して明言されていない洞察/制限がある場合 (可能性が非常に高い)、多くの最適化が可能です。例えば:

  • 特定のフィルターが常に使用されることがわかっていて、潜在的な一致を管理可能な数 (たとえば < ~100) にすぐに削減する場合は、最初にそれを使用し、その後のフィルタリングのためにブルート フォース検索に頼ることができます。

別の可能性は、個々のファイル名のプロパティを構造体に抽出することですstd::string data_type; std::vector<int> p;。次に、「p には 924 と data_type == 'XYZ' が含まれています」などの述語をサポートする式エバリュエーターを記述します。より高速なインデックスベースのマッチング。

外部ライブラリを使用したくないとおっしゃっていたことは承知していますが、ニーズが本当に複雑な範囲にある場合は、メモリ内データベースと SQL のようなクエリ機能を使用すると、多くの悲しみを救うことができます。

于 2011-05-27T05:11:11.257 に答える
1

まず第一に、あなたのデザインは非常にスマートで、モデル化しようとしている種類の動作に適していると思います。

とにかく、あなたは一種の「ドメイン固有言語」を構築しようとしていると理解しています。これにより、アクションを表す「動詞」(さまざまなフィルタリング方法)を連鎖させたり、「エンティティ」(可変性が異なるこれについては何も言いませんが、存在する可能性のある命名形式)。

この点に関して、非常に興味深い議論が Martin Flowler の著書「Domain Specific Languages」に見られます。それが何であるかの味を示すために、ここでは、次のように定義された「メソッド連鎖」パターンに関する興味深い議論を見つけることができます。

「複数の修飾子を 1 つの式で呼び出すことができるように、修飾子メソッドがホスト オブジェクトを返すようにします。」</p>

ご覧のとおり、このパターンは、設計で想定しているチェーン メカニズムそのものを表しています。

ここに、そのような DSL を定義する際に興味深いことがわかったすべてのパターンのリストがあります。繰り返しになりますが、デザインに暗示している、またはより一般的なパターン (デコレータなど) として記述しているいくつかの特殊なパターンを簡単に見つけることができます。それらのいくつかは次のとおりです。Regex Table Lexer、Method Chaining、Expression Builder など。設計をさらに詳細に指定するのに役立つその他多数。

全体として、あなたの仕様には「コマンド プロセッサ」パターンの場所があると言って差し支えないかもしれませんが、Fowler が提案する強力な抽象化を展開することで、あなたが思いつくことができると確信しています。 GoF パターン セットの「一般性」によって現在は単純に隠されている問題の側面をカバーする、より具体的で正確な設計を使用します。

これは、あなたが説明しているような問題に対して「やり過ぎ」になる可能性があることは事実ですが、パターン指向の設計の演習として、非常に洞察に満ちたものになる可能性があります。

于 2011-05-30T21:20:49.733 に答える
1

戦略パターンを使用します。DataManager は DataSet タイプを構築しており、DataSet には FilteringPolicy が割り当てられています。デフォルトは、フィルターなしを意味する NullFilteringPolicy にすることができます。DataSet メンバー関数 filter_type(string t) が呼び出されると、フィルター ポリシー クラスが新しいものと交換されます。新しいものは、filter_type パラメータを介して工場で構築できます。filter_run() などのメソッドを使用して、フィルター条件を FilterPolicy に追加できます。NullFilterPolicy の場合は、ノーオペレーションです。これは私には簡単に思えます。これが役立つことを願っています。

EDIT:メソッドチェーンに対処するには、 *this; を返すだけです。たとえば、DataSet クラスへの参照を返します。これは、DataSet メソッドを連結できることを意味します。これは、operator>> または operator<< を実装するときに C++ iostream ライブラリが行うことです。

于 2011-05-23T21:57:09.850 に答える
0

ブースト イテレータ ライブラリから始めることをお勧めします。たとえば、フィルタ イテレータです。

(もちろん、boost には非常に優れた正規表現ライブラリが含まれています。)

于 2011-05-14T20:37:00.867 に答える