2014-02-27 36 views
6

我有兩個自定義類Grid,並ElementLINQ的大名單

public class Grid 
{ 
    public double ID { get; set; } 

    public double X { get; set; } 
    public double Y { get; set; } 
    public double Z { get; set; } 

    public MyClass MoreProperties {get; set;} 

    public Grid(int id, double x, double y, double z) 
    { 
     this.ID = id; 
     this.X = x; 
     this.Y = y; 
     this.Z = z; 
    } 
} 

Element

public abstract class Element 
{ 
    public int ID { get; set; } 

    public int NumberOfGrids { get; set; } 

    public List<Grid> Grids { get; set; } //4 Grids in this case 

    public Element() 
    { 
     Grids = new List<Grid>();    
    } 
} 

爲了說明情況,請看到這樣的畫面:

enter image description here

那裏是的類的容器叫Data

class Data : ModelBase 
{ 
    public List<Grid> Grids{ get; set; } 

    public List<Element> Elements { get; set; } 
} 

我讀,其中有大量的數據的文本文件:編制和元素 這是網格格式(簡體):

GRID ID XYZ

而對於元件

元ID GRID1 GRID2 GRID3 GRID4

因此,GRID條目提供一個網格點的位置和ID和ELEMENT提供了元素的網格和它自己的ID的ID。

我想要的是爲每個元素關聯所有4個網格,這樣我就會得到元素對象的每個網格內部的座標

爲了讓我讀取文件兩次(因爲元素條目在網格之前並簡化了一些事情):我第一次閱讀它時填充了Grids列表(來自Data類)。 第二次填寫Elements列表並做更多的事情。當我填寫Elements列表時,我只能填寫關聯的Grid的ID。

如果您已閱讀,直到此處我們有此類包含兩個列表GridElements的數據。

,爲聯想,我想出這個方法:

public void AsociateGridsToElements() 
{ 
    foreach (Element elem in Elements) 
    { 
     for (int i = 0; i < elem.Grids.Count; i++) 
     { 
      elem.Grids[i] = Grids.Where(g => g.ID == elem.Grids[i].ID).FirstOrDefault(); 
     } 
    } 
} 

它通過循環的每個元素,然後通過(在這種情況下4)該元素的每個格子,然後它會在整個列表網格有哪些網格具有相同的ID。當它找到第一個元素時,它指定該網格,這樣元素具有「完整的」對象,而不是僅填充了ID的元素(因爲它是我讀取文件時唯一可以獲得的)。

問題在於:這些文件非常大:大約有20 000個網格點和10000個元素,如果我爲每個元素循環查看每次整個網格集合(4次),它是:20 000 x 10 000 = 200 000 000次操作。所以電腦無法處理它,我認爲它必須得到改善。

任何人都可以提供一個提示或幫助我優化這個問題嗎?謝謝。

回答

6

如果每個Grid對象的ID都保證是唯一的,那麼我將首先創建一個Grid對象的字典,並將ID作爲字典中的鍵。然後,在元素枚舉期間對填充的Grid進行查找將只需要字典查找而不是列表的新列表。

public void AsociateGridsToElements() 
{ 
    var gridLookup = Grids.ToDictionary(grid => grid.ID); 

    foreach (Element elem in Elements) 
    { 
     for (int i = 0; i < elem.Grids.Count; i++) 
     { 
      Grid fullyPopulatedGrid; 
      if (gridLookup.TryGetValue(elem.Grids[i].ID, out fullyPopulatedGrid)) 
      { 
       elem.Grids[i] = fullyPopulatedGrid; 
      } 
      else 
      { 
       // Unable to locate Grid Element 
      } 
     } 
    } 
} 

在這種情況下創建字典查找會顯着提高性能,因爲它可以防止額外列舉Grids列表。

代碼(根據你的估計)以上執行以下操作:

  1. 枚舉所有Grid項目,併爲每個項目一個鍵值對。 (約20,000步)
  2. 枚舉所有Element項目(約10000步)
  3. 枚舉,每個部分GridElement(稱之爲4步)
  4. 在字典進行查找,找到正確填充Grid(1哈希查找)

這裏的總步數約爲20000 +(10,000 * 4)* 2(每個元件/網格1個哈希查找)= 100,000步驟

你的原始代碼執行下列Ò perations:

  1. 枚舉所有Element項目(約10000步)
  2. 枚舉在Element(稱之爲4步)
  3. 枚舉所有填充Grid項目(約20,000步)每個部分Grid找到第一匹配(這需要每個元素/網格組合的單獨迭代)

這裏的總步驟大約是10,000 * 4 * 20,000 = 800,000,000步驟

+0

這似乎工作非常好,但我需要多一點的測試。你能否解釋一下這裏發生的事情,以及爲什麼表現增加了這麼多? – Sturm

+0

我用一些關於操作次數的估計更新了我的答案。 – davisoa

+3

如果可以的話,我會多投幾次。謝謝 – Sturm