96

I think this might be a pretty simple question, but I haven't been able to figure it out yet. If I've got a 2-dimensional array like so:

int[,] array = new int[2,3] { {1, 2, 3}, {4, 5, 6} };

What's the best way to iterate through each dimension of the array with a nested foreach statement?

philkark
  • 2,417
  • 7
  • 38
  • 59
Tyler Murry
  • 2,705
  • 3
  • 29
  • 46

12 Answers12

158

If you want to iterate over every item in the array as if it were a flattened array, you can just do:

foreach (int i in array) {
    Console.Write(i);
}

which would print

123456

If you want to be able to know the x and y indexes as well, you'll need to do:

for (int x = 0; x < array.GetLength(0); x += 1) {
    for (int y = 0; y < array.GetLength(1); y += 1) {
        Console.Write(array[x, y]);
    }
}

Alternatively you could use a jagged array instead (an array of arrays):

int[][] array = new int[2][] { new int[3] {1, 2, 3}, new int[3] {4, 5, 6} };
foreach (int[] subArray in array) {
    foreach (int i in subArray) {
        Console.Write(i);
    }
}

or

int[][] array = new int[2][] { new int[3] {1, 2, 3}, new int[3] {4, 5, 6} };
for (int j = 0; j < array.Length; j += 1) {
    for (int k = 0; k < array[j].Length; k += 1) {
        Console.Write(array[j][k]);
    }
}
ICR
  • 13,896
  • 4
  • 50
  • 78
  • 2
    After seeing the err of my ways (e.g. trying to use a 2D array like a jagged array), I agree the best way to iterate through that list is just like you have it in your first example. You get the vote because of your willingness to go beyond the answer and give other options. – Tyler Murry May 24 '10 at 15:06
  • Why is the 2-dim array flatten? – Michael Haddad Jan 11 '19 at 13:34
25

Here's how to visit each element in a 2-dimensional array. Is this what you were looking for?

for (int i=0;i<array.GetLength(0);i++)
{
    for (int j=0;j<array.GetLength(1);j++)
    {
        int cell = array[i,j];
    }
}
Daniel Plaisted
  • 16,674
  • 4
  • 44
  • 56
8

With multidimensional arrays, you can use the same method to iterate through the elements, for example:

int[,] numbers2D = new int[3, 2] { { 9, 99 }, { 3, 33 }, { 5, 55 } };
foreach (int i in numbers2D)
{
    System.Console.Write("{0} ", i);
}

The output of this example is:

9 99 3 33 5 55

References


In Java, multidimensional arrays are array of arrays, so the following works:

    int[][] table = {
            { 1, 2, 3 },
            { 4, 5, 6 },
    };
    for (int[] row : table) {
        for (int el : row) {
            System.out.println(el);
        }
    }
polygenelubricants
  • 376,812
  • 128
  • 561
  • 623
  • 3
    C# has multidimensional and jagged arrays as seperate concepts, where `int[,]` is a 2 dimensional array, and `int[][]` is a jagged array of arrays and each given array is not required to have the same length. You can easily do a foreach on the jagged array, but a 2D array is not the same type of structure. At any rate, your second snippet doesn't fit *this* problem, the first snippet isn't nested. – Anthony Pegram May 23 '10 at 20:40
5

I know this is an old post, but I found it through Google, and after playing with it think I have an easier solution. If I'm wrong please point it out, 'cuz I'd like to know, but this worked for my purposes at least (It's based off of ICR's response):

for (int x = 0; x < array.GetLength(0); x++)
{
    Console.Write(array[x, 0], array[x,1], array[x,2]);
}

Since the both dimensions are limited, either one can be simple numbers, and thus avoid a nested for loop. I admit I'm new to C#, so please, if there's a reason not to do it, please tell me...

Keven M
  • 972
  • 17
  • 47
  • 1
    This is assuming the length of the 2nd dimension. You're hardcoding the assumption that the second dimension will always have length 3, which may or may not be the case. If it's not 3 but, say, 50, you'll be looking at a lot of copy/pasting and making your code unreadable. :) – Adam Lear Jul 28 '11 at 13:54
  • @AnnaLear The assumption is not necessarily wrong, you might be processing a matrix of a well defined length such as 15x15 scrabble board – Jaycee Jan 03 '14 at 13:49
4

Use LINQ .Cast<int>() to convert 2D array to IEnumerable<int>.

LINQPad example:

var arr = new int[,] { 
  { 1, 2, 3 }, 
  { 4, 5, 6 } 
};

IEnumerable<int> values = arr.Cast<int>();
Console.WriteLine(values);

Output:

Sequence is 1,2,3,4,5,6

angularsen
  • 8,160
  • 1
  • 69
  • 83
3

The 2D array in C# does not lend itself well to a nested foreach, it is not the equivalent of a jagged array (an array of arrays). You could do something like this to use a foreach

foreach (int i in Enumerable.Range(0, array.GetLength(0)))
    foreach (int j in Enumerable.Range(0, array.GetLength(1)))
        Console.WriteLine(array[i, j]);

But you would still use i and j as index values for the array. Readability would be better preserved if you just went for the garden variety for loop instead.

Anthony Pegram
  • 123,721
  • 27
  • 225
  • 246
  • 1
    This is a horrible mutation of a classic, simple and understandable construct. If your code contains this, you really need to be thinking "hey, this works, but... how about not?" (I'm well aware this is idiomatic in the python family. However - This is C#.) – Rubys May 23 '10 at 20:49
  • @Rubys, this is not idiomatic in Python either. It is very unpythonic to get the indexes then access the list with `[]`. It is idiomatic Python to iterate over values directly. Also note that there are no multi-dimensional arrays or lists in Python (only jagged). – Matthew Flaschen May 23 '10 at 20:55
  • @Matthew: I may have confused python with another language, I don't really know my arms from my legs in the scripting family (which is what I meant in python family, I suppose) – Rubys May 23 '10 at 21:21
2

As mentioned elsewhere, you can just iterate over the array and it will produce all results in order across all dimensions. However, if you want to know the indices as well, then how about using this - https://ericlippert.com/2010/06/28/computing-a-cartesian-product-with-linq/

then doing something like:

var dimensionLengthRanges = Enumerable.Range(0, myArray.Rank).Select(x => Enumerable.Range(0, myArray.GetLength(x)));
var indicesCombinations = dimensionLengthRanges.CartesianProduct();

foreach (var indices in indicesCombinations)
{
    Console.WriteLine("[{0}] = {1}", string.Join(",", indices), myArray.GetValue(indices.ToArray()));
}
Daniel Smith
  • 309
  • 3
  • 9
2

Two ways:

  1. Define the array as a jagged array, and use nested foreachs.
  2. Define the array normally, and use foreach on the entire thing.

Example of #2:

int[,] arr = { { 1, 2 }, { 3, 4 } };
foreach(int a in arr)
    Console.Write(a);

Output will be 1234. ie. exactly the same as doing i from 0 to n, and j from 0 to n.

Rubys
  • 3,167
  • 2
  • 25
  • 26
2

You can use an extension method like this:

internal static class ArrayExt
{
    public static IEnumerable<int> Indices(this Array array, int dimension)
    {
        for (var i = array.GetLowerBound(dimension); i <= array.GetUpperBound(dimension); i++)
        {
            yield return i;
        }
    }
}

And then:

int[,] array = { { 1, 2, 3 }, { 4, 5, 6 } };
foreach (var i in array.Indices(0))
{
    foreach (var j in array.Indices(1))
    {
        Console.Write(array[i, j]);
    }

    Console.WriteLine();
}

It will be a bit slower than using for loops but probably not an issue in most cases. Not sure if it makes things more readable.

Note that c# arrays can be other than zero-based so you can use a for loop like this:

int[,] array = { { 1, 2, 3 }, { 4, 5, 6 } };
for (var i = array.GetLowerBound(0); i <= array.GetUpperBound(0); i++)
{
    for (var j= array.GetLowerBound(1); j <= array.GetUpperBound(1); j++)
    {
        Console.Write(array[i, j]);
    }

    Console.WriteLine();
}
Dmitriy
  • 3,305
  • 7
  • 44
  • 55
Johan Larsson
  • 17,112
  • 9
  • 74
  • 88
1
int[,] arr =  { 
                {1, 2, 3},
                {4, 5, 6},
                {7, 8, 9}
              };
 for(int i = 0; i < arr.GetLength(0); i++){
      for (int j = 0; j < arr.GetLength(1); j++)
           Console.Write( "{0}\t",arr[i, j]);
      Console.WriteLine();
    }

output:  1  2  3
         4  5  6
         7  8  9
Sohel Ahmed
  • 31
  • 1
  • 4
1

I was looking for a solution to enumerate an array of an unknown at compile time rank with an access to every element indices set. I saw solutions with yield but here is another implementation with no yield. It is in old school minimalistic way. In this example AppendArrayDebug() just prints all the elements into StringBuilder buffer.

public static void AppendArrayDebug ( StringBuilder sb, Array array )
{
    if( array == null || array.Length == 0 )
    {
        sb.Append( "<nothing>" );
        return;
    }

    int i;

    var rank = array.Rank;
    var lastIndex = rank - 1;

    // Initialize indices and their boundaries
    var indices = new int[rank];
    var lower = new int[rank];
    var upper = new int[rank];
    for( i = 0; i < rank; ++i )
    {
        indices[i] = lower[i] = array.GetLowerBound( i );
        upper[i] = array.GetUpperBound( i );
    }

    while( true )
    {
        BeginMainLoop:

        // Begin work with an element

        var element = array.GetValue( indices );

        sb.AppendLine();
        sb.Append( '[' );
        for( i = 0; i < rank; ++i )
        {
            sb.Append( indices[i] );
            sb.Append( ' ' );
        }
        sb.Length -= 1;
        sb.Append( "] = " );
        sb.Append( element );

        // End work with the element

        // Increment index set

        // All indices except the first one are enumerated several times
        for( i = lastIndex; i > 0; )
        {
            if( ++indices[i] <= upper[i] )
                goto BeginMainLoop;
            indices[i] = lower[i];
            --i;
        }

        // Special case for the first index, it must be enumerated only once
        if( ++indices[0] > upper[0] )
            break;
    }
}

For example the following array will produce the following output:

var array = new [,,]
{
    { {  1,  2,  3 }, {  4,  5,  6 }, {  7,  8,  9 }, { 10, 11, 12 } },
    { { 13, 14, 15 }, { 16, 17, 18 }, { 19, 20, 21 }, { 22, 23, 24 } }
};

/*
Output:

[0 0 0] = 1
[0 0 1] = 2
[0 0 2] = 3
[0 1 0] = 4
[0 1 1] = 5
[0 1 2] = 6
[0 2 0] = 7
[0 2 1] = 8
[0 2 2] = 9
[0 3 0] = 10
[0 3 1] = 11
[0 3 2] = 12
[1 0 0] = 13
[1 0 1] = 14
[1 0 2] = 15
[1 1 0] = 16
[1 1 1] = 17
[1 1 2] = 18
[1 2 0] = 19
[1 2 1] = 20
[1 2 2] = 21
[1 3 0] = 22
[1 3 1] = 23
[1 3 2] = 24
*/
dmitry1100
  • 1,199
  • 12
  • 26
1

You can also use enumerators. Every array-type of any dimension supports the Array.GetEnumerator method. The only caveat is that you will have to deal with boxing/unboxing. However, the code you need to write will be quite trivial.

Here's the sample code:

class Program
{
    static void Main(string[] args)
    {
        int[,] myArray = new int[,] { { 1, 2 }, { 3, 4 }, { 5, 6 } };
        var e = myArray.GetEnumerator();

        e.Reset();

        while (e.MoveNext())
        {
            // this will output each number from 1 to 6. 
            Console.WriteLine(e.Current.ToString());
        }

        Console.ReadLine();
    }
}
code4life
  • 15,655
  • 7
  • 50
  • 82
  • Vote -1... I quote msdn `Using foreach is recommended, instead of directly manipulating the enumerator.` – Ivan Jan 09 '17 at 21:30