2

データを除外するためのアルゴリズムを教えてください。

私はjavascriptを使用して、データの配列をフィルタリングするフィルター関数を書き出そうとしています。データの配列とフィルターの配列があるので、すべてのデータに各フィルターを適用するために、2つのforループを記述しました。

foreach(data)
{
  foreach(filter)
  {
   check data with filter
  }
}

これは適切なコードではありませんが、要するに、私の関数が行うことは、これには膨大な時間がかかるということです。誰かがより良い方法を提案できますか。

私はMootoolsライブラリを使用しており、データの配列はJSON配列です

データとフィルターの詳細

データはユーザーと言うことができるJSON配列なので、

data = [{"name" : "first", "email" :  "first@first", "age" : "20"}.
        {"name" : "second", "email" :  "second@second", "age" : "21"}
        {"name" : "third", "email" :  "third@third", "age" : "22"}]

フィルタの配列は、基本的に、データのさまざまなフィールドの自己定義クラスです。

alFilter[0] = filterName;
alFilter[1] = filterEmail;
alFilter[2] = filterAge;

したがって、最初のforループに入ると、上記の場合、単一のJSONオブジェクト(最初の行)が得られます。2番目のforループ(filters loop)に入ると、現在のフィルターが機能する正確なフィールドを抽出し、データの適切なフィールドでフィルターをチェックするフィルタークラスがあります。

だから私の例では

foreach(data)
{
 foreach(filter)
{
  //loop one - filter name
 // loop two - filter email
 // loop three - filter age
}
}

2番目のループが終了すると、データがフィルタリングされているかどうかを示すフラグを設定し、それに応じてデータが表示されます。

4

5 に答える 5

3

実際に役立つようにするには、データとフィルターの正確な構造についてさらに詳細を提供する必要があります。フィルターは、データのサブセットを選択するため、またはデータを変更するために使用されていますか? フィルターは何をしているのですか?

とはいえ、いくつかの一般的な提案があります。

  1. 仕事を減らす。作業しているデータの量を制限する方法はありますか? メインループを実行する前に、すばやく実行してカットできるプレフィルターはありますか?
  2. できるだけ早く内側のループから抜け出してください。フィルターの 1 つがデータムを拒否した場合、内側のループから抜け出し、次のデータムに進みます。これが可能な場合は、最も選択的なフィルターを最初に配置するようにしてください。(これは、フィルターがアイテムを変更するのではなく、リストから除外するために使用されていることを前提としています)
  3. フィルターが実行する計算の冗長性をチェックします。それらのそれぞれがいくつかのサブルーチンを共有するいくつかの複雑な計算を実行する場合、おそらくメモ化または動的プログラミングを使用して冗長な計算を回避できます。

実際、それはすべて、コードの 3 つのレベルすべてで、最初のポイントであるdo less workに要約されます。外側のループの項目を制限することで、作業を減らすことができますか? 特定のフィルターの後で停止し、最も選択的なフィルターを最初に実行することで、作業を減らしますか? 各フィルター内で冗長な計算を行わないことで作業が減りますか?

于 2009-04-15T21:20:01.510 に答える
2

それはあなたがそれを行うべき方法です。トリックは、その「フィルターでデータをチェックする」部分を最適化することです。すべてのデータをトラバースし、すべてのフィルターと照合する必要があります。これ以上速くなることはありません。

文字列の比較を避け、データ モデルをできるだけネイティブに使用し、各パスでデータ セットを減らすようにしますfilter

さらに知識がなければ、これを最適化することは困難です。

于 2009-04-15T21:20:28.483 に答える
2

フィルターの適用をソートして、2 つのことが最適化されるようにする必要があります。高価なチェックを最後に、大量のデータを排除するチェックを最初に行う必要があります。次に、「アウト」の結果が発生するとすぐにチェックが短くなるようにする必要があります。

于 2009-04-15T23:32:05.563 に答える
1

フィルターが特定の値、範囲、またはテキストの開始を探している場合、jOrder ( http://github.com/danstocker/jorder ) が問題に適合します。

次のように jOrder テーブルを作成するだけです。

var table = jOrder(data)
    .index('name', ['name'], { grouped: true, ordered: true })
    .index('email', ['email'])
    .index('age', ['age'], { grouped: true, ordered: true, type: jOrder.number });

table.where()次に、テーブルをフィルタリングするために呼び出します。

完全一致を探している場合:

filtered = table.where([{name: 'first'}, {name: 'second'}]);

1 つのフィールドの特定の範囲を探している場合:

filtered = table.where([{age: {lower: 20, upper: 21}}], {mode: jOrder.range});

または、特定の文字列で始まる値を探している場合:

filtered = table.where([{name: 'fir'}], {mode: jOrder.startof});

この方法では、ネストされたループよりもフィルタリングが大幅に高速になります。

于 2010-07-14T09:53:08.260 に答える
0

一致しない場合にフィルターがデータを削除すると仮定すると、次のように 2 つのループを切り替えることをお勧めします。

foreach(filter) {
    foreach(data) {
        check data with filter
    }
}

そうすることで、2 番目のフィルターはすべてのデータを処理する必要はなく、最初のフィルターを通過したデータのみを処理する必要があります。もちろん、上記のヒント (高価なチェックを最後に行うなど) は依然として真実であり、さらに考慮する必要があります。

于 2009-04-16T14:53:17.807 に答える