c# – 将键/值对列表转换为datatable
我正在研究解析器.它从源文本中获取值.它事先不知道它将获得多少或哪些值,即变量的名称,它们的数量等可能变化很大.源的每个部分仅提供一些值,而不是完整列表.这些值当前存储在自定义类的列表中,类似于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 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. 只是有关尺寸的信息: 并再次强调.只有DataTable让我担心.亮点,分段,源检索,过滤等 – 都符合我的期望.所以我首先要看 – 一种优化从键/值对列表转换到DataTable的方法,或者最初(处理后)以不同方式存储这些值的方法来加速过程. 希望这能提供足够的信息.目前没有列出来源以减小尺寸. 解决方法
我会在这里寻找除DataTable之外的数据结构.听起来像你需要的是Dictionary< string,Dictionary< int,CustomValue>> ;.字符串是您的列名,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,则可以使用计数器变量(静态或随每次调用传递),以便每个对象具有不同的ID. 按行存储值可能更有意义,每个数据集具有的列,而不是相反的列.这将是一个IEnumerable< Dictionary< string,CustomValue>> ;,每个Dictionary代表一行.您将使用target.Select(x => x.Key).Distinct()拉出所有列. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |