试图制作一个二维数组列表

Posted

技术标签:

【中文标题】试图制作一个二维数组列表【英文标题】:Trying to make a 2D array of lists 【发布时间】:2010-11-17 11:15:13 【问题描述】:

我正在尝试编写一个包含数字生物的模型。在模型中,我认为环境是一个固定的二维数组,但每个单元格都需要包含其中的生物体列表。我尝试使用锯齿状数组,但由于在整个程序运行过程中占用元素的数量变化很大,我需要使用比数组更灵活的东西。我尝试制作类型列表的二维数组,但我遇到了错误。

    List<Creature>[,] theWorld;


    public Environment()
     
        List<Creature>[,] theWorld = new List<Creature>[100,100];
    

    public void addCreature(Creature c)
    
       for (int x = 0; x < 100; x++)
        
            for (int y = 0; y < 100; y++)
            
                theWorld[x, y].Add (c);

              

这是我试图在开头声明数组的部分,作为保存(生物体)列表的类型,后来我尝试将生物(c)添加到每个列表中的每个列表中数组的元素。

当我运行它时,我收到以下错误消息-

“在 HGT_sim_2.exe 中发生了“System.NullReferenceException”类型的未处理异常

附加信息:对象引用未设置为对象的实例。"

和行“World[x, y].Add (c);”突出显示。

如果有人能告诉我我做错了什么,甚至更好的解决问题的方法,那就太棒了。 提前谢谢你!

【问题讨论】:

在映射二维数组时,通常 y 先出现,然后是 x,但我猜顺序是主观的。 y then x 会从左上角给出准确的视觉输出。 【参考方案1】:

您的数组最初包含的所有内容都是很多空值。您需要实际创建列表...

for(int x = 0 ; x < 100 ; x++)
    for(int y = 0 ; y < 100 ; y++)
        theWorld[x,y] = new List<Creature>();

不过,就我个人而言,我认为这将是一种代价高昂的做事方式......

这部分取决于数据是否“稀疏”——即大多数单元格是否通常被占用?例如,一种简单(但可能更有效)的方法是使用多地图之类的东西;即

Point pt = new Point(x,y);
theWorld.Add(pt, someCreature);

其中theWorld 可能类似于EditableLookup&lt;Point, Creature&gt;(使用来自“MiscUtil”的EditableLookup&lt;,&gt;)。这样,您仍然可以通过坐标查询它,并且在一个坐标上 有多个生物,但您不必为每个单元格分配空间。而且因为它的功能是字典,所以它仍然很快。 不如平面数组快,但它会扩展到更大(稀疏)的网格......当然,如果网格的每个单元格上都有生物,它可能会更多昂贵的!因此需要了解您的数据。

【讨论】:

PowerCollections 包含一个 MultiDictionary 这会有所帮助 确实如此。如果您在某个时候还没有编写自己的多地图,那么您还没有尝试过;-p【参考方案2】:

您需要初始化数组的每个成员,例如

for (int x = 0; x < 100; x++)
    
        for (int y = 0; y < 100; y++)
        
            theWorld[x, y] = new List<Creature>();

         

【讨论】:

PS ...在您发布添加到列表的代码之前执行此操作;-) 刚刚发现这个用途! :) 谢谢!【参考方案3】:

解决方法如下:

List<Creature>[,] theWorld;


public Environment()
 
    theWorld = new List<Creature>[100,100]; // Remove the type, you were creating a new list and throwing it away...

    for(int x = 0 ; x < 100 ; x++)
       for(int y = 0 ; y < 100 ; y++)
          theWorld[x,y] = new List<Creature>();    


public void addCreature(Creature c)

   for (int x = 0; x < 100; x++)
    
        for (int y = 0; y < 100; y++)
        
            theWorld[x, y].Add (c);

          

【讨论】:

在构造函数中添加了注释告诉你。【参考方案4】:

当你这样做时:

List<Creature>[,] theWorld = new List<Creature>[100,100];

您正在创建一个 List&lt;Creature&gt; 引用数组,但它们都是空的(指向 null,不是有效的列表)。您需要初始化每个单独的元素:

for (int x = 0; x < 100; x++) 
    for (int y = 0; y < 100; y++) 
       theWorld[i,j] = new List<Creature>();
    

完成此操作后,您就可以在各个成员上调用 .Add。

【讨论】:

【参考方案5】:

你做的几乎是正确的。您的变量是List&lt;Creature&gt; 的二维数组。现在,List&lt;Creature&gt; 是一个引用类型,因此数组被初始化为在其所有成员中包含null。这样你就得到了NullReferenceException。线

theWorld[x, y].Add (c);

基本上等价于

null.Add (c);

您需要做的就是初始化所有成员以包含List&lt;Creature&gt; 的实例。最好的方法是在构造函数中。只需像这样重写它:

public Environment()
 
    theWorld = new List<Creature>[100,100];
    for(int x = 0 ; x < 100 ; x++)
        for(int y = 0 ; y < 100 ; y++)
            theWorld[x,y] = new List<Creature>();

现在所有操作都将按预期进行。

另请注意,在您的示例中,您正在创建一个与类成员同名的局部变量。这样,您根本不会初始化类成员 - 它保持为空。

【讨论】:

【参考方案6】:

您已经创建了数组对象来保存您的列表,但您还没有创建列表本身。您需要在构造函数中执行以下操作:

for (int x = 0; x < 100; x++) 
    for (int y = 0; y < 100; y++)
        theWorld[x,y] = new List<Creature>();

另一个问题:您还在构造函数中将theWorld 定义为局部变量,这意味着Environment 上的theWorld 字段也从未初始化。

但是,10,000 Lists 可能对于您真正需要的东西来说太过分了。如果您的环境确实在每个点都需要Creature,并且一些生物可能会移动到其他点(在某个点有多个点,那么使用Dictionary&lt;Point, IList&lt;Creature&gt;&gt; 作为您的模型而不是 10,000 个列表可能更有意义.

public void Add(Creature c, Point at)

    IList<Creature> list;
    if (!theWorld.TryGetValue(at)) 
        list = theWorld[at] = new List<Creature>();
    
    list.Add(c);

然后您可以类似地实现MoveRemove 方法。另外,请注意您将相同生物添加到每个点,这(可能)意味着您的环境中的所有点都有一个生物。您可能希望为每个点创建一个new Creature(),如果这是您实际建模的内容。

【讨论】:

部分正确,但如果不修复构造函数中的代码,它将无法工作 已编辑以包含该建议和其他建议。

以上是关于试图制作一个二维数组列表的主要内容,如果未能解决你的问题,请参考以下文章

从二维数组python中删除引号

试图将一个连续的动态二维数组从 C 传递到 Fortran

试图将一个连续的动态二维数组从 C 传递到 Fortran

swift 如何在swift中制作一个二维数组

将二维数组转换为列表(一维)的快速方法

如何在 QT 中制作二维数组?