Итерация многомерного массива с вложенным оператором Foreach
Я думаю, что это может быть довольно простой вопрос, но я еще не смог понять это. Если у меня есть 2-мерный массив вот так:
int[,] array = new int[2,3] { {1, 2, 3}, {4, 5, 6} };
каков наилучший способ итерации по каждому измерению массива с вложенным foreach заявление?
11 ответов:
если вы хотите перебирать каждый элемент в массиве, как если бы это был сплющенный массив, вы можете просто сделать:
foreach (int i in array) { Console.Write(i); }
что бы напечатать
123456
если вы хотите знать индексы x и y, вам нужно будет сделать:
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]); } }
в качестве альтернативы вы можете использовать зубчатый массив вместо (массив массивов):
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); } }
или
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]); } }
вот как посетить каждый элемент в 2-мерном массиве. Это то, что вы ищете?
for (int i=0;i<array.GetLength(0);i++) { for (int j=0;j<array.GetLength(1);j++) { int cell = array[i,j]; } }
С многомерными массивами, вы можете использовать тот же метод для перебора элементов, например:
int[,] numbers2D = new int[3, 2] { { 9, 99 }, { 3, 33 }, { 5, 55 } }; foreach (int i in numbers2D) { System.Console.Write("{0} ", i); }
вывод этого примера:
9 99 3 33 5 55
ссылки
в Java многомерные массивы являются массивами массивов, поэтому следующие работы:
int[][] table = { { 1, 2, 3 }, { 4, 5, 6 }, }; for (int[] row : table) { for (int el : row) { System.out.println(el); } }
Я знаю, это старый пост, но я нашел его через Google, и после игры с ним я думаю есть более простое решение. Если я ошибаюсь, пожалуйста, укажите на это, потому что я хотел бы знать, но это сработало для моих целей, по крайней мере (это основано на ответе ICR):
for (int x = 0; x < array.GetLength(0); x++) { Console.Write(array[x, 0], array[x,1], array[x,2]); }
2D массив в C# не очень хорошо поддается вложенному foreach, он не является эквивалентом зубчатого массива (массив массивов). Вы могли бы сделать что-то подобное, чтобы использовать 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]);
но вы все равно будете использовать i и j в качестве значений индекса для массива. Читаемость была бы лучше сохранена, если бы вы просто пошли на садовый сорт
for
вместо петли.
два варианта:
- определение массива как массива массивов, и использовать вложенные foreachs.
- определить массив нормально, и использовать foreach на всю вещь.
Пример #2:
int[,] arr = { { 1, 2 }, { 3, 4 } }; foreach(int a in arr) Console.Write(a);
выход будет 1234. то есть. точно так же, как я делаю от 0 до n, а j от 0 до n.
вы можете использовать метод расширения такой:
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; } } }
и затем:
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(); }
Это будет немного медленнее, чем использование для циклов, но, вероятно, не проблема в большинстве случаев. Не уверен, что это делает вещи более читабельными.
обратите внимание, что массивы c# могут быть отличными от нуля, поэтому вы можете использовать цикл for следующим образом:
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(); }
можно также использовать перечислители. Каждый тип массива любого измерения поддерживает массив.Метод GetEnumerator. Единственный нюанс заключается в том, что вам придется иметь дело с бокс/распаковка. Однако код, который вам нужно написать, будет довольно тривиальным.
вот пример кода:
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(); } }
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
Как уже упоминалось в другом месте, вы можете просто перебрать массив и он будет производить все результаты в порядке по всем направлениям. Однако, если вы также Хотите знать индексы, то как насчет использования этого - http://blogs.msdn.com/b/ericlippert/archive/2010/06/28/computing-a-cartesian-product-with-linq.aspx
затем делать что-то вроде:
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())); }