Я думаю, что это может быть довольно простой вопрос, но я еще не смог его понять. Если у меня есть такой двумерный массив:
int[,] array = new int[2,3] { {1, 2, 3}, {4, 5, 6} };
Какой лучший способ перебрать каждое измерение массива с помощью вложенного оператора foreach ?
c#
foreach
nested-loops
Тайлер Мерри
источник
источник
Ответы:
Если вы хотите перебрать каждый элемент в массиве, как если бы это был плоский массив, вы можете просто сделать:
foreach (int i in array) { Console.Write(i); }
который напечатает
Если вы хотите знать индексы 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]); } }
источник
Вот как можно посетить каждый элемент двумерного массива. Это то, что ты искал?
for (int i=0;i<array.GetLength(0);i++) { for (int j=0;j<array.GetLength(1);j++) { int cell = array[i,j]; } }
источник
Рекомендации
В Java многомерные массивы представляют собой массивы массивов, поэтому работает следующее:
int[][] table = { { 1, 2, 3 }, { 4, 5, 6 }, }; for (int[] row : table) { for (int el : row) { System.out.println(el); } }
источник
int[,]
- это двухмерный массив иint[][]
зубчатый массив массивов, и каждый заданный массив не обязательно должен иметь одинаковую длину. Вы можете легко выполнить foreach для массива с зазубринами, но 2D-массив - это не тот же тип структуры. Во всяком случае, ваш второй фрагмент не подходит для этой задачи, первый фрагмент не вложен.Я знаю, что это старый пост, но я нашел его через Google, и, поиграв с ним, думаю, что у меня есть более простое решение. Если я ошибаюсь, укажите это, потому что я хотел бы знать, но это сработало, по крайней мере, для моих целей (это основано на ответе ICR):
for (int x = 0; x < array.GetLength(0); x++) { Console.Write(array[x, 0], array[x,1], array[x,2]); }
Поскольку оба измерения ограничены, любое из них может быть простыми числами, что позволяет избежать вложенного цикла for. Признаюсь, я новичок в C #, поэтому, пожалуйста, если есть причина не делать этого, скажите мне ...
источник
Двумерный массив в 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
вместо этого вы просто пошли по кругу .источник
[]
. Идиоматический Python - перебирать значения напрямую. Также обратите внимание, что в Python нет многомерных массивов или списков (только зубчатые).Два пути:
Пример №2:
На выходе будет 1234. т.е. точно так же, как выполнение i от 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(); }
Это будет немного медленнее, чем использование циклов for, но, вероятно, в большинстве случаев это не проблема. Не уверен, что это делает вещи более читаемыми.
Обратите внимание, что массивы 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(); }
источник
Как упоминалось в другом месте, вы можете просто перебирать массив, и он выдаст все результаты по порядку во всех измерениях. Однако, если вы также хотите узнать индексы, то как насчет этого - 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())); }
источник
Используйте LINQ
.Cast<int>()
для преобразования 2D-массива вIEnumerable<int>
.Пример LINQPad:
var arr = new int[,] { { 1, 2, 3 }, { 4, 5, 6 } }; IEnumerable<int> values = arr.Cast<int>(); Console.WriteLine(values);
Вывод:
источник
Вы также можете использовать счетчики. Каждый тип массива любого измерения поддерживает метод Array.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(); } }
источник
Using foreach is recommended, instead of directly manipulating the enumerator.
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
источник
Я искал решение для перечисления массива неизвестных во время компиляции ранга с доступом к каждому набору индексов элементов. Я видел решения с yield, но вот еще одна реализация без yield. Это в стиле олдскульного минимализма. В этом примере AppendArrayDebug () просто печатает все элементы в буфер StringBuilder.
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; } }
Например, следующий массив выдаст следующий результат:
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 */
источник