2015-04-14 67 views
1
比較

我處理2個數據表:C#值2點的DataTable

  1. SSFE:包含的價值觀,我想找到
  2. FFE:是大於,小於或同樣大SSFE,但不一定包含SSFE的每個值

我需要在這些表之間匹配的值是整數,兩個表都按從小到大排序。 我的想法是開始搜索FFE的第一個項目,開始循環SSFE,當我找到一個匹配 - >記住當前索引 - >保存匹配 - >從FFE選擇下一個項目並繼續從上一個索引。

此外,FFE可以包含整數,但也可以包含字符串,這就是爲什麼我將值轉換爲字符串並進行比較的原因。

我做了一些代碼,但它需要太多的時間。 將SSFE(1.000項)與FFE(127.000)項目進行比較需要大約一分鐘的時間。

int whereami = 0; 
bool firstiteration = true; 
for (int i = 0; i < FFEData.Rows.Count - 1; i++) 
{ 
    for (int j = 0; j < SSFEData.Rows.Count - 1; j++) 
    { 
     if (firstiteration) 
     { 
      j = whereami; 
      firstiteration = false; 
     } 
     if (SSFEData.Rows[j][0] == FFEData.Rows[i][0].ToString()) 
     { 
      found++; 
      whereami = j; 
      firstiteration = true; 
      break; 
     } 
    } 
} 

我只存儲了多少次我發現用於測試的事件。在這個例子中,它會找到490個匹配,而不是這是相關的。

任何建議將是偉大的!

+0

[codereview.se]可能會比這個問題更像SO。也就是說,像'ToString'這樣的東西讓我覺得效率低下,'where'變量也不清楚它應該做什麼,但我敢打賭,'firstiteration'測試可以通過一些邏輯變化來消除。 – paqogomez

+0

另外,我發現數據表非常慢。如果將這些數據填充到自己的對象中,則可以使用linq將它們連接在一起並找到匹配項。這不會是一個加速,但它會讓你的代碼更具可讀性。 – paqogomez

+0

@paqogomez在這種情況下,這是一個局部變量,用於存儲當前索引'j'。數據實際上是填充在我自己的對象中的,通過Linq加入這兩個表不是一個選項。因爲應用程序必須儘可能短,這是因爲它運行在非常重要的生產服務器上,這些服務器沒有足夠的內存用於複雜和長時間運行的任務。目前使用大約200MB的RAM,當執行這個Linq程序時,它將會建立到約600MB,這太多了。 –

回答

0

可以嘗試DataRelation類。它在DataSet中的兩個DataTable之間創建一個外鍵/聯接。

using System.Data; 
using System.Text; 

public int GetMatches(DataTable table1, DataTable table2) 
{ 
    DataSet set = new DataSet(); 

    //wrap the tables in a DataSet. 
    set.Tables.Add(table1); 
    set.Tables.Add(table2); 

    //Creates a ForeignKey like Join between two tables. 
    //Table1 will be the parent. Table2 will be the child. 
    DataRelation relation = new DataRelation("IdJoin", table1.Columns[0], table2.Columns[0], false); 

    //Have the DataSet perform the join. 
    set.Relations.Add(relation); 

    int found = 0; 

    //Loop through table1 without using LINQ. 
    for(int i = 0; i < table1.Rows.Count; i++) 
    { 
     //If any rows in Table2 have the same Id as the current row in Table1 
     if (table1.Rows[i].GetChildRows(relation).Length > 0) 
     { 
      //Add a counter 
      found++; 

      //For debugging, proof of match: 
      //Get the id's that matched. 
      string id1 = table1.Rows[i][0].ToString(); 

      string id2 = table1.Rows[i].GetChildRows(relation)[0][0].ToString(); 

     } 
    } 

    return found; 
} 

我用nvarchar(2)字符串隨機填充兩個非索引表,每個字符串有10,000行。比賽花了1秒鐘,包括填充表格的時間。平均而言,我會得到3500到4000場比賽。

但是,主要的警告是,匹配的DataColumns 必須是是相同的數據類型。所以如果兩列都是字符串,或者至少是整數存儲爲字符串,那麼這將工作。

但是,如果一列是一個整數,您將不得不添加一個新列,並將整數作爲字符串存儲在該列中。字符串翻譯將增加大量時間。

另一種選擇是將表上載到數據庫並執行查詢。那麼大的上傳可能需要幾秒鐘,但查詢也會在一秒之內。所以仍然比60秒+更好。

+0

這工作就像一個魅力!現在比較實際上比運行填充它們的查詢需要更少的時間。謝謝! –