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

更新:所有加载和处理都是预先完成的。就绪数据存储为已处理部分的树。作为属性之一的每个部分都包含一个键/值对列表。每个部分都有类来用它的值填充给定的 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)当前级别列表中的所有可用值,并将它们一次添加到目标 DataTable 1,然后检查 DataColumn 是否存在所需的名称(target[Value.Key]!=null) - 并创建列如果需要,在尝试添加相应的值之前。在元代码中:

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);
}

为什么这个特定的部分 - 值只是类似例程的一部分。其他例程在相同的数据集上进行类似的爬网,检索其他内容(主要使用列表,没有 DataTables)——所有这些都可以立即工作。虽然收集 DataTable 可能需要几秒钟才能让 1 个源得到填充的结果 DataGrid。

值的平均数量很少超过 1000(例如,10 列乘 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。


按行存储值可能更有意义,每组数据具有列,而不是相反。那将是 a IEnumerable<Dictionary<string, CustomValue>>,每个Dictionary代表一行。您将使用 . 拉出所有列target.Select(x => x.Key).Distinct()

于 2012-12-21T19:26:14.240 回答
0

数据表很慢。它做了很多事情。

如果你们都是字符串,那么我会创建一个集合

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

List<ColValues> RowsColValues;

然后,您需要使用 ColValues[i] 语法手动将列绑定到 DataGrid。

为了提高速度,请为此使用 ListView GridView。
与 Gridview 相比,DataGrid 速度慢且体积大。
但 GridView 不编辑。

不编造这个。
我正是这样做的,但情况不同。
用户选择他们想要查看的列。

动态柱

于 2012-12-21T17:10:38.267 回答