views:

186

answers:

5

How do you create a multi-dimensional data structure in C#?

In my mind it works like so:

 List<List<int>> results = new List<List<int>>();
    for (int i = 0; i < 10; i++)
    {
        for (int j = 0; j < 10; j++)
        {
            results[i][j] = 0;
        }
    }

This doesn't work (it throws an ArgumentOutOfRangeException). Is there a multi-dimensional structure in C# that allows me to access members through their indexes?

A: 

You could use a datatable and add columns and rows? You would then be able to reference them by name or index.

IPX Ares
+2  A: 

You have to create the lists and initialize them with zeros before you can't start indexing into them.

    List<List<int>> results = new List<List<int>>();

    for (int i = 0; i < 10; i++)
    {
        results.Add(new List<int>(Enumerable.Repeat(0, 10)));
    }
Mark Byers
+2  A: 

You have to actually 1) create each of the inner lists, and 2) set them to that size.

var Results = Enumerable.Range(0, 10).Select(i => Enumerable.Repeat(0, 10).ToList()).ToList();

I'm a bit of a Linq addict, though.

Chris
Me too :-). This is my preferred way of doing it, so I added it into my answer as well. What's this `for` thing everyone keeps using? :o)
Zooba
+9  A: 

The problem here is that List doesn't automatically create elements. To initialise a List<List<T>> you need something like this:

List<List<int>> results = new List<List<int>>();

for (int i = 0; i < 10; i++)
{
    results.Add(new List<int>());
    for (int j = 0; j < 10; j++)
    {
        results[i].Add(0);
    }
}

Note that setting Capacity is not sufficient, you need to call Add the number of times you need. Alternatively, you can simplify things by using Linq's Enumerable class:

List<List<int>> results = new List<List<int>>();

for (int i = 0; i < 10; i++)
{
    results.Add(new List<int>());
    results[i].AddRange(Enumerable.Repeat(0, 10));
}

Again, note that Enumerable.Repeat(new List<int>(), 10) will not work, since it will add 10 references to the same list.

Another approach using Linq to the extreme:

List<List<int>> results = Enumerable.Repeat(0, 10)
    .Select(i => Enumerable.Repeat(0, 10).ToList())
    .ToList();

(The unused parameter i is necessary to ensure that you don't reference the same list ten times as discussed above.)

Finally, to access elements, you can use exactly the notation you used before. Once the elements have been added, they can be read or modified as shown:

for (int i = 0; i < 10; i++)
{
    for (int j = 0; j < 10; j++)
    {
        results[i][j] = 2;
        int x = results[i][j];
    }
}
Zooba
I need a dynamic structure, initializing it ahead of time wont work...
Jack Null
Well, then you either include code to ensure you have enough elements already added before you access it, or you use `Dictionary<int,Dictionary<int,int>>`.
Zooba
+2  A: 

If you know the dimensions of your structure in advance, and you do not plan to add or remove elements, then a 2D array sounds like your thing:

int[,] n = new int[10, 20];
for (int i = 0; i < 10; ++i) {
    for (int j = 0; j < 10; ++j) {
        n[i, j] = ...
    };
};
Pavel Minaev