Попытка сделать 2D массив списков

Это означает часто не иметь необходимость проверить на нулевые объекты везде для безопасности - особенно:

[someVariable release];

или, как отмечено, различные методы количества и длины весь возврат 0, когда у Вас есть нулевое значение, таким образом, Вы не должны добавлять дополнительные проверки на ноль на всем протяжении:

if ( [myString length] > 0 )

или это:

return [myArray count]; // say for number of rows in a table
8
задан svick 15 July 2012 в 10:02
поделиться

6 ответов

Изначально весь ваш массив содержит много нулей. Вам действительно нужно создать списки ...

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

Лично я полагаю, что это будет дорогостоящий способ сделать что-то ...

Это частично зависит от того, являются ли данные "разреженными", т.е. из ячеек обычно берутся? Например, простой (но, возможно, более эффективный) подход заключался бы в использовании чего-то вроде multi-map; т.е.

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

где theWorld может быть чем-то вроде EditableLookup (с использованием EditableLookup <,> из « MiscUtil » ). Таким образом, вы все еще можете запрашивать его по координате и иметь несколько существ на координате, но вам не нужно выделять место для каждой ячейки. И поскольку он работает как словарь, он по-прежнему работает быстро. Не как быстрый, как плоский массив, но он будет масштабироваться до больших (разреженных) сеток ... конечно, если в каждой ячейке сетки есть существа, это может быть дороже ! Следовательно, необходимо понимать ваши данные.

8
ответ дан 5 December 2019 в 13:00
поделиться

Вам необходимо инициализировать каждый элемент вашего массива, например

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

        } }
3
ответ дан 5 December 2019 в 13:00
поделиться

Когда вы делаете это:

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

Вы создаете массив Список ссылок , но все они пустые (указывают на нуль, а не на действительный список). Вам необходимо инициализировать каждый отдельный элемент:

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

Как только вы это сделаете, вы сможете вызывать .Add для отдельных членов.

0
ответ дан 5 December 2019 в 13:00
поделиться

Вот исправление:

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);

        } } }
2
ответ дан 5 December 2019 в 13:00
поделиться

Вы делаете это почти правильно. Ваша переменная представляет собой двумерный массив List . Теперь List является ссылочным типом, поэтому массив инициализируется, чтобы содержать null во всех своих элементах. Таким образом, вы получаете NullReferenceException . Строка

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

в основном эквивалентна

null.Add (c);

Все, что вам нужно сделать, это инициализировать все члены, содержащие экземпляры List . Лучше всего это сделать в конструкторе. Просто перепишите это так:

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>();
}

Теперь все операции будут работать, как ожидалось.

Также обратите внимание, что в вашем примере вы создаете локальную переменную с тем же именем, что и член класса. Таким образом, вы вообще не инициализируете член класса - он останется нулевым.

0
ответ дан 5 December 2019 в 13:00
поделиться

Вы создали объект массива для хранения ваших списков, но вы не создали сам список. В конструкторе вам нужно будет сделать следующее:

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

Другая проблема: вы также определяли theWorld как локальную переменную в своем конструкторе, что означает ваше поле theWorld на ] Среда также никогда не была инициализирована.

Однако 10 000 List могут оказаться излишними для того, что вам действительно нужно. Если вашей Среде действительно требуется Существо в каждой точке, и некоторые Существа могут перемещаться в другие точки (если их больше одного, тогда может иметь смысл использовать Словарь < Укажите, IList > в качестве вашей модели по сравнению с 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);
}

Затем можно реализовать методы Переместить и Удалить аналогичным образом. Также обратите внимание, что вы добавляете одно и то же Существо в каждую точку, что (может) означать, что во всех точках вашей Среды есть одно Существо. Вы, вероятно, захотите создать новое Существо () для каждой точки, если это то, что вы на самом деле моделируете.

0
ответ дан 5 December 2019 в 13:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: