我如何通过二维阵列'预先'?

Sco*_*ham 45 c# arrays multidimensional-array

我有一个二维数组,

string[,] table = {
                       { "aa", "aaa" },
                       { "bb", "bbb" }
                   };
Run Code Online (Sandbox Code Playgroud)

我想像这样foreach通过它,

foreach (string[] row in table)
{
    Console.WriteLine(row[0] + " " + row[1]);
}
Run Code Online (Sandbox Code Playgroud)

但是,我得到错误:

无法将类型字符串转换为字符串[]

有没有办法可以达到我想要的效果,即用迭代器变量迭代数组的第一维,然后返回该行的一维数组?

Mar*_*tos 60

多维数组不可枚举.只需重复老式的方式:

for (int i = 0; i < table.GetLength(0); i++)
{
    Console.WriteLine(table[i, 0] + " " + table[i, 1]);
}
Run Code Online (Sandbox Code Playgroud)

  • 一个小点:多维数组*是*可枚举的,只是不像OP想要的那样. (10认同)
  • 好的,@ Odrade,我会授予你的. (3认同)
  • 实际上做了OP想要的,因此是最好的答案。(尽管只是在“做我想做的事而不是我要求的事”的意义上!) (2认同)

Odr*_*ade 26

正如其他人的建议,你可以使用嵌套的for循环或重新声明您的多维数组的锯齿状之一.

但是,我认为值得指出的是,多维数组可枚举的,而不是你想要的方式.例如:

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

foreach (string s in table)
{
    Console.WriteLine(s);
}

/* Output is:
  aa
  aaa
  bb
  bbb
*/
Run Code Online (Sandbox Code Playgroud)


Rad*_*tov 25

如果你这样定义你的数组:

string[][] table = new string[][] { new string[] { "aa", "aaa" }, new string[]{ "bb", "bbb" } };
Run Code Online (Sandbox Code Playgroud)

然后你可以在它上面使用foreach循环.

  • ...因为那时它是一个数组的数组.这也意味着你的阵列可能是锯齿状的. (2认同)
  • 这不是2D数组.它是一个数组中的数组.这与使用普通数组一样有效,在具有X和Y参数的getter和setter以及使用x*width + y公式的类中. (2认同)
  • 没有对“foreach”+错误方式的解释或示例 (2认同)

Dan*_*Tao 15

更新:我有一些时间在我的手上,所以...我继续前进并充实了这个想法.请参阅下面的代码.


这是一个疯狂的答案:

可以做你正在寻找的东西 - 基本上将二维数组视为一个带有行的表 - 通过编写一个静态方法(可能是一个扩展方法)来获取T[,]并返回一个IEnumerable<T[]>.但是,这需要将基础表的每个"行"复制到一个新数组中.

一个或许更好(虽然更复杂)的方法是实际编写一个实现IList<T>为二维数组的单个"行"包装的类(你可能设置IsReadOnly为true并且只为该this[int]属性实现getter 并且可能Count并且GetEnumerator;其他一切都可能抛出a NotSupportedException).然后,您的静态/扩展方法可以返回IEnumerable<IList<T>>并提供延迟执行.

这样你就可以像编写的那样编写代码:

foreach (IList<string> row in table.GetRows()) // or something
{
    Console.WriteLine(row[0] + " " + row[1]);
}
Run Code Online (Sandbox Code Playgroud)

只是一个想法.


实施建议:

public static class ArrayTableHelper {
    public static IEnumerable<IList<T>> GetRows<T>(this T[,] table) {
        for (int i = 0; i < table.GetLength(0); ++i)
            yield return new ArrayTableRow<T>(table, i);
    }

    private class ArrayTableRow<T> : IList<T> {
        private readonly T[,] _table;
        private readonly int _count;
        private readonly int _rowIndex;

        public ArrayTableRow(T[,] table, int rowIndex) {
            if (table == null)
                throw new ArgumentNullException("table");

            if (rowIndex < 0 || rowIndex >= table.GetLength(0))
                throw new ArgumentOutOfRangeException("rowIndex");

            _table = table;
            _count = _table.GetLength(1);
            _rowIndex = rowIndex;
        }

        // I didn't implement the setter below,
        // but you easily COULD (and then set IsReadOnly to false?)
        public T this[int index] {
            get { return _table[_rowIndex, index]; }
            set { throw new NotImplementedException(); }
        }

        public int Count {
            get { return _count; }
        }

        bool ICollection<T>.IsReadOnly {
            get { return true; }
        }

        public IEnumerator<T> GetEnumerator() {
            for (int i = 0; i < _count; ++i)
                yield return this[i];
        }

        // omitted remaining IList<T> members for brevity;
        // you actually could implement IndexOf, Contains, etc.
        // quite easily, though
    }
}
Run Code Online (Sandbox Code Playgroud)

...现在我想我应该让StackOverflow休息一天;)


Mat*_*ias 7

这取决于您如何定义多维数组。这里有两个选项:

using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            // First
            string[,] arr1 = {
                       { "aa", "aaa" },
                       { "bb", "bbb" }
                   };

            // Second
            string[][] arr2 = new[] {
                new[] { "aa", "aaa" },
                new[] { "bb", "bbb" }
            };

            // Iterate through first
            for (int x = 0; x <= arr1.GetUpperBound(0); x++)
                for (int y = 0; y <= arr1.GetUpperBound(1); y++)
                    Console.Write(arr1[x, y] + "; ");

            Console.WriteLine(Environment.NewLine);

            // Iterate through second second
            foreach (string[] entry in arr2)
                foreach (string element in entry)
                    Console.Write(element + "; ");

            Console.WriteLine(Environment.NewLine);
            Console.WriteLine("Press any key to finish");
            Console.ReadKey();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Mat*_*son 5

这是一个简单的扩展方法,它将每一行作为IEnumerable<T>. 这具有不使用任何额外内存的优点:

public static class Array2dExt
{
    public static IEnumerable<IEnumerable<T>> Rows<T>(this T[,] array)
    {
        for (int r = array.GetLowerBound(0); r <= array.GetUpperBound(0); ++r)
            yield return row(array, r);
    }

    static IEnumerable<T> row<T>(T[,] array, int r)
    {
        for (int c = array.GetLowerBound(1); c <= array.GetUpperBound(1); ++c)
            yield return array[r, c];
    }
}
Run Code Online (Sandbox Code Playgroud)

示例用法:

static void Main()
{
    string[,] siblings = { { "Mike", "Amy" }, { "Mary", "Albert" }, {"Fred", "Harry"} };

    foreach (var row in siblings.Rows())
        Console.WriteLine("{" + string.Join(", ", row) + "}");
}
Run Code Online (Sandbox Code Playgroud)