6

30000行のcsvファイルがあります。多くの条件に基づいて多くの値を選択する必要があるため、多くのループと「if」を使用してlinqを使用することにしました。csvを読むためのクラスを作成しました。linqで使用するIEnumerableを実装します。これは私の列挙子です:

class CSVEnumerator : IEnumerator
{

    private CSVReader _csv;

    private int _index;

    public CSVEnumerator(CSVReader csv)
    {
        _csv = csv;
        _index = -1;
    }

    public void Reset(){_index = -1;}


    public object Current
    {
        get
        {
            return new CSVRow(_index,_csv);
        }
    }


    public bool MoveNext()
    {
        return ++_index < _csv.TotalRows;
    }

}

動作していますが、遅いです。100;150行の範囲の列Aで最大値を選択するとします。

max  = (from CSVRow r in csv where r.ID > 100 && r.ID < 150 select r).Max(y=>y["A"]);

これは機能しますが、linqは48行ではなく30000行で最大値を検索します。前述したように、ループを使用できますが、この例の場合のみ、条件は「残忍」です:)

linqコレクション検索をオーバーライドする方法はありますか?次のようなものです。列挙子で使用されているクエリを調べ、「where」のlinq条件に「rowID filter」が含まれているかどうかを調べ、これに基づいて別のデータを提供します。

データの一部を別の配列/コレクションにコピーしたくないのですが、csvリーダーに問題はありません。idですべての行にアクセスするのは高速ですが、問題は30000個すべてにアクセスする場合だけです。必要なヘルプ:-)

4

3 に答える 3

2

これにLINQを効率的に使用できるようにするには、SQLデータベース用のさまざまなLINQプロバイダーと同様の(ただしはるかに単純な)方法で式ツリーを使用する必要があります。実行可能ですが、このような単純なタスクにはかなりのコードになると思います。

そのため、別の方法を使用して必要な行を選択する(そして、おそらくLINQを使用して結果を処理する)のがより良い解決策になると思います。

また、コレクションを返す多くの操作(元のコードと私の変更を含む)は、イテレーターメソッドを使用して簡略化できます。

したがって、コードは次のようになります。

public static IEnumerable<CSVRow> GetRows(
    this CSVReader reader, int idGreaterThan, int idLessThan)
{
    for (int i = idGreaterThan + 1; i < idLessThan; i++)
    {
        yield return new CSVRow(reader, i);
    }
}

ここでは、の拡張メソッドですCSVReaderが、別のソリューション(たとえば、そのクラスの実際のメソッド)の方が適している場合があります。

この場合、例は次のようになります。

max = csvReader.GetRows(100, 150).Max(y => y["A"]);

(また、制限が100から150の場合、実際には101から149の行が必要になるのは奇妙だと思います。しかし、それには理由があると思いますので、同じようにしました。)

于 2013-01-01T01:05:27.583 に答える
1

LINQに関する限り、r.IDは単にフィルター処理される値であるため、すべての30k行がMax操作での使用が考慮されます。これが行インデックスである場合(ここに当てはまるようです)、Skip and Takeを使用して、すべての30k行を比較することを回避できます。

max = csv.Skip(100).Take(50).Max(y => y["A"]);
于 2013-01-01T00:01:57.317 に答える
0

@DougMは評価の順序については正しいですが、この場合、初期化を1回ヒットして、「インデックス」フィールドのルックアップを生成します。基本的に、行インデックスから行へのマップ(辞書)を事前に計算します。 。とは言うものの、これは、特定のインデックスフィールドに対して何度もクエリを繰り返す場合にのみ役立ちます。

于 2013-01-01T00:12:12.670 に答える