4

私はパーサーに取り組んでいます。ソーステキストから値を取得します。取得する値の数、つまり、変数の名前、その数などは大きく異なる可能性があることを事前に知りません。ソースの各セクションは、完全なリストではなく、一部の値のみを提供します。これらの値は現在、KeyValuePair に似たカスタム クラスのリストに格納されていますが、最初から記述されています。

ソースから取得されるサンプル:

Section 1:
    KeyA = ValA1
    KeyB = ValB1
    KeyD = ValD1
Section 2:
    KeyC = ValC2
Section 3:
    KeyB = ValB3
    KeyD = ValD3

ここで、この情報を次の形式の DataGrid としてユーザーに表示したいと思います。

| KeyA  | KeyB  | KeyC  | KeyD  |
+-------+-------+-------+-------+
| ValA1 | ValB1 |       | ValD1 |
|       |       | ValC2 |       |
|       | ValB3 |       | ValD3 |

現在、各セクションで見つかったすべての値を繰り返し処理しています。列が存在するかどうかを確認し、存在しない場合は新しい列を作成しています。列が存在する場合 - それぞれの行/列に値を追加します。次に、結果の DataTable を DataGrid に次のようにアタッチします。

dg.ItemSource=dt.AsDataView();

これは意図したとおりに完全に機能しますが、遅すぎます。

どうすればそれをスピードアップできるかについての考えをいただければ幸いです。最初の格納、DataTable への変換、またはデータをバインドしてユーザーに同じプレゼンテーションを実現するその他の方法のいずれかです。

C#、WPF、.NET フレームワーク 4.5

更新:すべての読み込みと処理は事前に行われます。準備完了データは、処理されたセクションのツリーとして保存されます。プロパティの 1 つとしての各セクションは、キーと値のペアのリストを保持します。各セクションには、指定された DataTable にその値を設定するためのクラスがあります。

つまり、バックエンドのデータは次のようになります。

File1
  + Section 1 on level 1
  |   + Section 1
  |   + Section 2
  + Section 2 on level 1
  + Section 3 on level 1
  |   + Section 1
  |   + Section 2
  |   + Section 3
  |   + Section 4
  + Section 4
File2 ...

各セクションにはメソッドがあります:

public void CollectValues(DataTable target) {...}

これは、いくつかの DataTable を持つ上位レベルの要素によって呼び出されます (最初は空で、進むにつれていっぱいになります)。

各セクションには内部変数が含まれています。

private List<CustomValue> Values;

CustomValue クラスで既に見つかって処理されたすべての値を保持します。CustomValue ~= KeyValuePair ですが、処理ルーチンが追加されています。

したがって、CollectValues は要求されたレベル (トップの可能性もあれば、他のレベルの可能性もあります) から空の未準備の DataTable で呼び出されます。CollectValues は、現在のレベルのリストで使用可能なすべての値を (foreach) 反復処理し、必要な名前 (target[Value.Key]!=null) を持つ DataColumn が存在するかどうかを確認する前に、それらをターゲット DataTable 1 に一度に追加し、列を作成します。必要に応じてそれぞれの値を追加しようとする前に。メタコード:

public void CollectValues(DataTable target)
{
    DataRow dr = target.Rows.Create();
    foreach(var pair in Values)
    {
        if(target[pair.Key]==null) target.Columns.Add(...);
        dr[pair.Key] = pair.Value;
    }
    foreach(var child in Children)
        child.CollectValues(target);
}

なぜこの特定の部分 - 値は同様のルーチンの一部にすぎません。他のルーチンは、同じデータセットを同様にクロールし、他のものを取得します (主にリストで動作し、DataTable は使用しません) - それらはすべてほぼ瞬時に動作します。ただし、DataTable の収集には、結果の DataGrid が設定される 1 つのソースに対して数秒かかる場合があります。

値の平均量が 1000 を超えることはめったにありません (10 列 x 100 行など)。DataTable は、完全に設定された後にのみ DataGrid にアタッチされます。

サイズに関する情報: ソース - 通常 2 ~ 10 ファイル。各ソース テキストのサイズは 100Kb ~ 100 MB の範囲です。通常のファイル サイズは約 1 ~ 2 MB です。通常、メモリ内のバックエンド データのサイズは 100 MB 未満です。

そして再びハイライト。私が心配しているのは DataTable だけです。ハイライト、セクショニング、ソース検索、フィルタリングなど - すべてが期待どおりに機能します。したがって、私はまず第一に、キーと値のペアのリストから DataTable への変換を最適化する方法、またはそれらの値を最初に (処理後に) 別の方法で保存してプロセスを高速化する方法を探しています。

これで十分な情報が得られることを願っています。サイズを小さくするために、現在ソースをリストしていません。

4

2 に答える 2

1

ここで使用する DataTable 以外のデータ構造を探します。あなたが必要としているのはDictionary<string, Dictionary<int, CustomValue>>. はstring列名、intはデータ行の ID、そしてCustomValueはデータそのものです。

public void CollectValues(Dictionary<string, Dictionary<int, CustomValue>> target)
{
    foreach(var pair in Values)
    {
        if(target[pair.Key]==null) target.Add(new Dictionary<int, CustomValue>());
        target[pair.Key].Add(pair.ID, pair.Value);
    }
    foreach(var child in Children)
        child.CollectValues(target);
}

まだ配置されていない場合はpair.ID、カウンター変数 (staticまたは各呼び出しで渡される) を使用して、各オブジェクトが異なる ID を持つようにすることができます。


その逆ではなく、データの各セットが持つ列を使用して、行ごとに値を格納する方が理にかなっている場合があります。これはIEnumerable<Dictionary<string, CustomValue>>、それぞれDictionaryが 1 つの行を表す になります。ですべての列を引き出しますtarget.Select(x => x.Key).Distinct()

于 2012-12-21T19:26:14.240 に答える
0

DataTable が遅いです。それは多くのことをします。

あなたがすべて文字列の場合、コレクションを作成します

List<String> ColNames;
List<String> ColValues;

List<ColValues> RowsColValues;

次に、ColValues[i] 構文を使用して列を DataGrid に手動でバインドする必要があります。

速度を上げるために、これには ListView GridView を使用します。
DataGrid は、Gridview に比べて遅く、かさばります。
ただし、GridView は編集しません。

これを構成していません。
私はまさにこれを行いますが、別のシナリオです。
ユーザーは、表示する列を選択します。

動的列

于 2012-12-21T17:10:38.267 に答える