Reputation: 2815
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?
Upvotes: 98
Views: 141817
Reputation: 329
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()));
}
Upvotes: 2
Reputation: 1329
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
*/
Upvotes: 1
Reputation: 17580
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();
}
Upvotes: 2
Reputation: 8668
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:
Upvotes: 4
Reputation: 31
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
Upvotes: 1
Reputation: 992
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...
Upvotes: 5
Reputation: 15794
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();
}
}
Upvotes: 1
Reputation: 14162
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]);
}
}
Upvotes: 163
Reputation: 3207
Two ways:
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.
Upvotes: 2
Reputation: 383746
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
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);
}
}
Upvotes: 8
Reputation: 126854
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.
Upvotes: 3
Reputation: 16744
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];
}
}
Upvotes: 25