2012-12-21 42 views
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。

I.e.對後端數據的樣子:

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) {...} 

這是由一些數據表中更高級別的元素稱爲(最初 - 空的,因爲它會越來越充滿)。

每個部分包含內部變量:

private List<CustomValue> Values; 

保持所有已經發現&在CustomValue類處理的值。 CustomValue〜= KeyValuePair,但增加了處理例程。

所以會發生什麼情況是CollectValues被從要求的級別調用(可能是頂級的,可能是任何其他)與空毫無準備的DataTable。 CollectValues迭代(foreach)通過當前級別列表中的所有可用值,並在檢查DataColumn是否存在所需名稱(target [Value.Key]!= null)之前將它們一次添加到目標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的填充。

平均值很少超過1000(例如,10列乘100行)。 DataTable僅在完全填充後才附加到DataGrid。

僅供參考尺寸: 來源 - 通常爲2到10個文件。每個源文本大小的範圍可以是100Kb - 100 MB。通常的文件大小約爲1-2 MB。內存中後端數據的大小通常在100 MB以下。

並再次突出顯示。只有DataTable讓我擔心。亮點,分區,源檢索,過濾等 - 都符合我的預期。所以我首先要看的是 - 優化從鍵/值對列表到DataTable的轉換,或者最初(處理後)以不同方式存儲這些值的方式,以加快處理速度。

希望這給了足夠的信息。目前沒有列出源以減小大小。

+0

看起來像一個數據透視表。發佈創建主鍵的代碼。你如何檢索數據?延遲獲取數據的好機會,或數據量,而不是數據的實際操作。 –

+4

什麼是慢速部分? –

+0

數據單獨提取並存儲在已處理的後端中。這發生在選定的文件加載期間。只有完成所有的加載/處理 - 用戶才能使用界面。慢部分看起來是收集/轉換部分。它通過遍歷非常大的樹進行迭代,請求DataTable由每個節填充。 – chersun

回答

0

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

如果你是所有的字符串,那麼我會創建一個集合

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

List<ColValues> RowsColValues; 

然後,你需要手動綁定使用ColValues [i]語法列到DataGrid。

併爲此速度使用ListView GridView。
DataGrid速度較慢,並且與Gridview相比體積較大。
但是GridView不能編輯。

沒有這樣做。
我這樣做,但一個不同的場景。
用戶選擇他們想要查看的列。

DyamicColumns

+0

將嘗試GridView的變化。編輯實際上不是必需的,我可以詳細說明你的意思有點嗎?我需要價值名稱是標題和值在這種情況下,我不太清楚如何做到這一點 – chersun

+0

使用ColNames作爲標題 – Paparazzi

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()提取所有列。

+0

我對這樣的結構沒有太多的工作,看起來不錯,你能不能展示將字典詞典綁定到某種網格(gridview/datagrid)?它可以直接綁定到ItemsSource嗎? – chersun

+0

我經常使用Dictionary for ComboBox綁定。我將SelectedValuePath綁定到'Key'和DisplayMemberPath以'Value'。通過這種方式,我可以獲得1到5個不等的字符串,例如「apple」,「banana」等。用戶可以看到這些字符串,但是在向ComboBox詢問所選值時,我會得到與其關聯的密鑰(通常,數據庫p rimary ID)。 – Joe

+0

@chersun - 嗯。好問題。我不認爲它可以直接綁定,但你可能會從你需要的價值。 'target.Keys'是列表列表,'target.Values.Select(x => x.Values)'是每行的值列表。不過,我玩了一下,但我不確定這是讀取結果的最佳數據結構。我會編輯另一個建議。 – Bobson