2014-02-27 38 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