将键/值对列表转换为datatable

时间:2012-12-21 14:10:18

标签: c# wpf datagrid .net-4.5

我正在研究解析器。它从源文本中获取值。它事先不知道它将获得多少或哪些值,即变量的名称,它们的数量等可能变化很大。源的每个部分仅提供一些值,而不是完整列表。这些值当前存储在自定义类的列表中,类似于KeyValuePair,但是从头开始编写。

示例从源检索的内容:

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

现在,我想以以下形式向用户显示此信息:

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

目前,我正在遍历每个部分中找到的所有值,检查列是否存在 - 如果不存在 - 创建新列。如果列存在 - 向相应的行/列添加值。然后将结果DataTable附加到DataGrid:

dg.ItemSource=dt.AsDataView();

这完全符合预期,但这太慢了。

我很欣赏任何有关如何加快速度的想法。初始存储,或转换为DataTable,或其他一些绑定数据的方式,以实现与用户相同的演示。

C#,WPF,.NET framework 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虽然可能需要几秒钟才能生成一个源,以便生成DataGrid。

平均值的数量很少超过1000(例如,10列乘100行)。 DataTable仅在完全填充后附加到DataGrid。

仅提供尺码信息: 来源 - 通常是2到10个文件。每个源文本大小可以是100Kb - 100 MB。通常的文件大小约为1-2 MB。内存中后端数据的大小通常低于100 MB。

再次强调。只有DataTable让我担心。亮点,分段,源检索,过滤等 - 都符合我的期望。所以我首先要看 - 一种优化从键/值对列表转换到DataTable的方法,或者最初(处理后)以不同方式存储这些值的方法,以加快处理速度。

希望这能提供足够的信息。目前没有列出减少尺寸的来源。

2 个答案:

答案 0 :(得分: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代表一行。您可以使用target.Select(x => x.Key).Distinct()拉出所有列。

答案 1 :(得分:0)

DataTable很慢。它做了很多东西。

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

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

List<ColValues> RowsColValues;

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

为了速度,请使用ListView GridView。
DataGrid与Gridview相比速度很慢且很大 但是GridView不会编辑。

不这样做。
我这样做只是一个不同的场景 用户选择他们想要查看的列。

DyamicColumns