Linq在大名单中

Stu*_*urm 6 c# linq wpf

我有两个自定义类Grid,并且Element:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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>();              
    }
}
Run Code Online (Sandbox Code Playgroud)

为了说明这种情况,请看这张图:

在此输入图像描述

这个类有一个容器叫做Data:

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

    public List<Element> Elements { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我读过有大量数据的文本文件:网格和元素这是网格的格式(简化):

GRID ID XYZ

而对于元素

ELEMENT ID GRID1 GRID2 GRID3 GRID4

因此,该GRID条目提供网格点的位置和ID,并ELEMENT提供该元素的网格ID和它自己的ID.

我想要的是为每个元素关联所有4个网格,这样我将在元素对象内部拥有每个网格的坐标.

为此,我读了两次文件(因为元素条目出现在网格之前并简化了一些事情):第一次读到它时我填写了Grids列表(来自Data类).我第二次填写Elements列表并做更多的事情.当我填写Elements列表时,我只能填写相关的ID Grid.

如果你读到这里,我们有这个类数据包含两个Grid和的列表Elements.

对于协会,我想出了这个方法:

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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

它循环遍历每个元素,然后遍历该元素的每个网格(在这种情况下为4),然后它在整个网格列表中查找哪些网格具有相同的ID.当它找到第一个时,它会分配该网格,这样元素就有了"完整" Grid对象,而不是只填充了ID的对象(因为这是我读取文件时唯一能得到的东西).

这里谈到的问题:这些文件是相当大的:大约20 000个网格点和10 000元,如果我循环为每个元素每次找网格(4次)的整个集合,它是:20 000×10 000 = 200 000 000次行动.所以计算机无法处理它,我认为它必须得到改进.

任何人都可以提示或帮助我优化这个问题吗?谢谢.

dav*_*soa 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
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,创建字典查找可以显着提高性能,因为它可以防止格网列表的其他枚举.

上面的代码执行以下操作(根据您的估算):

  1. 枚举所有Grid项目并为每个项目创建一个键值对.(约20,000步)
  2. 枚举所有Element项目(约10,000步)
  3. 枚举每个部分GridElement(称之为4个步骤)
  4. 在字典上执行查找以找到正确填充的Grid(1哈希查找)

这里的总步数约为20,000 +(10,000*4)*2(每个元素/网格1个哈希查找)= 100,000步

您的原始代码执行以下操作:

  1. 枚举所有Element项目(约10,000步)
  2. 枚举每个部分GridElement(称之为4个步骤)
  3. 枚举所有填充的Grid项目(大约20,000步)以查找第一个匹配项(这需要为每个元素/网格组合单独迭代)

这里的总步数约为10,000*4*20,000 = 800,000,000步

  • 如果可以的话,我会多投票几次.谢谢 (3认同)