Как я 'foreach' через двумерный массив? - PullRequest
43 голосов
/ 14 мая 2010

У меня есть двумерный массив,

string[,] table = {
                       { "aa", "aaa" },
                       { "bb", "bbb" }
                   };

И я бы хотел foreach пройти через это,

foreach (string[] row in table)
{
    Console.WriteLine(row[0] + " " + row[1]);
}

Но я получаю ошибку:

Невозможно преобразовать строку типа в строку []

Есть ли способ, которым я могу достичь того, чего хочу, то есть перебрать первое измерение массива с помощью переменной итератора, возвращающей мне одномерный массив для этой строки?

Ответы [ 12 ]

0 голосов
/ 18 марта 2015

Я пытаюсь это. Я надеюсь помочь. Работает с

static void Main()
    {
        string[,] matrix = {
                               { "aa", "aaa" },
                               { "bb", "bbb" }
                           };
        int index = 0;
        foreach (string element in matrix)
        {
            if (index < matrix.GetLength(1))
            {
                Console.Write(element);
                if (index < (matrix.GetLength(1) - 1))
                {
                    Console.Write(" ");
                }
                index++;
            }
            if (index == matrix.GetLength(1))
            {
                Console.Write("\n");
                index = 0;
            }
        }
0 голосов
/ 12 марта 2015

Я не большой поклонник этого метода из-за задействованного использования памяти, но если вы используете создаваемые им массивы, это не такая трата.

public static void ForEachRow<T>(this T[,] list, Action<int, T[]> action)
{
    var len = list.GetLength(0);
    var sub = list.GetLength(1);

    T[] e;
    int i, j;

    for (i = 0; i < len; i++)
    {
        e = new T[sub];

        for (j = 0; j < sub; j++)
        {
            e[j] = list[i, j];
        }

        action(i, e);
    }
}

Реализация:

var list = new[,]{0x0, 0x1, 0x2, 0x4, 0x8};

list.ForEachRow((i, row) =>
{
    for (var j = 0; j < row.Length; j++)
    {
        Console.WriteLine("[{0},{1}]: {2}", i, j, row[j]);
    }
});

Другое решение, которое я нашел, требует меньше памяти, но будет использовать больше ЦП, особенно когда размеры записей массивов больше.

public static void ForEachRow<T>(this T[,] list, Action<int, IEnumerable<T>> action)
{
    var len = list.GetLength(0);
    var sub = list.GetLength(1);

    int i, j;
    IEnumerable<T> e;

    for (i = 0; i < len; i++)
    {
        e = Enumerable.Empty<T>();

        for (j = 0; j < sub; j++)
        {
            e = e.Concat(AsEnumerable(list[i, j]));
        }

        action(i, e);
    }
}

private static IEnumerable<T> AsEnumerable<T>(T add)
{
    yield return add;
}

Реализация:

var list = new[,]{0x0, 0x1, 0x2, 0x4, 0x8};

list.ForEachRow((i, row) =>
{
    var j = 0;

    forrach (var o in row)
    {
        Console.WriteLine("[{0},{1}]: {2}", i, j, o);

        ++j;
    }
});

В целом, я считаю, что первый вариант более интуитивно понятен, особенно если вы хотите получить доступ к производимому массиву с помощью его индексатора.

В конце концов, это всего лишь конфетка, ни один из методов не должен использоваться для прямого доступа к исходному массиву;

for (var i = 0; i < list.GetLength(0); i++)
{
    foreach (var j = 0; j < list.GetLength(1); j++)
    {
        Console.WriteLine("[{0},{1}]: {2}", i, j, list[i, j]);
    }
}
...