【问题标题】:How do you loop through a multidimensional array?你如何循环遍历一个多维数组?
【发布时间】:2012-03-07 06:01:04
【问题描述】:
foreach (String s in arrayOfMessages)
{
    System.Console.WriteLine(s);
}

string[,] arrayOfMessages 正在作为参数传入。

我希望能够确定哪些字符串来自arrayOfMessages[0,i]arrayOfMessages[n,i],其中n 是数组的最终索引。

【问题讨论】:

  • 那为什么不直接使用带索引的循环呢?

标签: c# .net arrays c#-4.0 multidimensional-array


【解决方案1】:

不要使用foreach - 使用嵌套的for 循环,数组的每个维度一个。

可以通过GetLength方法获取每个维度的元素个数。

请参阅 MSDN 上的 Multidimensional Arrays (C# Programming Guide)

【讨论】:

    【解决方案2】:

    使用嵌套的 for 循环:

    for (int row = 0; row < arrayOfMessages.GetLength(0); row++)
    {
       for (int col = 0; col < arrayOfMessages.GetLength(1); col++)
       {
          string message = arrayOfMessages[row,col];
          // use the message
       }    
    }
    

    【讨论】:

      【解决方案3】:

      只需使用两个嵌套的for 循环。要获取维度的大小,可以使用GetLength()

      for (int i = 0; i < arrayOfMessages.GetLength(0); i++)
      {
          for (int j = 0; j < arrayOfMessages.GetLength(1); j++)
          {
              string s = arrayOfMessages[i, j];
              Console.WriteLine(s);
          }
      }
      

      这假设您实际上拥有string[,]。在 .Net 中,也可能有不从 0 开始索引的多维数组。在这种情况下,它们必须在 C# 中表示为 Array,您需要使用 GetLowerBound()GetUpperBound() 来获取边界每个维度。

      【讨论】:

        【解决方案4】:

        这样的事情会起作用:

        int length0 = arrayOfMessages.GetUpperBound(0) + 1;
        int length1 = arrayOfMessages.GetUpperBound(1) + 1;
        
        for(int i=0; i<length1; i++) { string msg = arrayOfMessages[0, i]; ... }
        for(int i=0; i<length1; i++) { string msg = arrayOfMessages[length0-1, i]; ... }
        

        【讨论】:

          【解决方案5】:

          您可以使用下面的代码来运行多维数组。

          foreach (String s in arrayOfMessages)
          {
              System.Console.WriteLine("{0}",s);
          }
          

          【讨论】:

            【解决方案6】:

            看起来您找到了适合您的问题的答案,但是由于标题要求提供多维数组(我读为 2 或更多),这是我得到的第一个搜索结果搜索时,我将添加我的解决方案:

            public static class MultidimensionalArrayExtensions
            {
                /// <summary>
                /// Projects each element of a sequence into a new form by incorporating the element's index.
                /// </summary>
                /// <typeparam name="T">The type of the elements of the array.</typeparam>
                /// <param name="array">A sequence of values to invoke the action on.</param>
                /// <param name="action">An action to apply to each source element; the second parameter of the function represents the index of the source element.</param>
                public static void ForEach<T>(this Array array, Action<T, int[]> action)
                {
                    var dimensionSizes = Enumerable.Range(0, array.Rank).Select(i => array.GetLength(i)).ToArray();
                    ArrayForEach(dimensionSizes, action, new int[] { }, array);
                }
                private static void ArrayForEach<T>(int[] dimensionSizes, Action<T, int[]> action, int[] externalCoordinates, Array masterArray)
                {
                    if (dimensionSizes.Length == 1)
                        for (int i = 0; i < dimensionSizes[0]; i++)
                        {
                            var globalCoordinates = externalCoordinates.Concat(new[] { i }).ToArray();
                            var value = (T)masterArray.GetValue(globalCoordinates);
                            action(value, globalCoordinates);
                        }
                    else
                        for (int i = 0; i < dimensionSizes[0]; i++)
                            ArrayForEach(dimensionSizes.Skip(1).ToArray(), action, externalCoordinates.Concat(new[] { i }).ToArray(), masterArray);
                }
            
                public static void PopulateArray<T>(this Array array, Func<int[], T> calculateElement)
                {
                    array.ForEach<T>((element, indexArray) => array.SetValue(calculateElement(indexArray), indexArray));
                }
            }
            

            使用示例:

            var foo = new string[,] { { "a", "b" }, { "c", "d" } };
            foo.ForEach<string>((value, coords) => Console.WriteLine("(" + String.Join(", ", coords) + $")={value}"));
            // outputs:
            // (0, 0)=a
            // (0, 1)=b
            // (1, 0)=c
            // (1, 1)=d
            
            // Gives a 10d array where each element equals the sum of its coordinates:
            var bar = new int[4, 4, 4, 5, 6, 5, 4, 4, 4, 5];
            bar.PopulateArray(coords => coords.Sum());
            

            一般的想法是通过维度向下递归。我确信这些函数不会赢得效率奖,但它可以作为我的格的一次性初始化程序,并带有一个足够好的 ForEach 来公开值和索引。我还没有解决的主要缺点是让它自动从数组中识别 T,所以在类型安全方面需要小心。

            【讨论】:

              【解决方案7】:

              更实用的方法是使用 LINQ,我总是发现它比循环更好。它使代码更具可维护性和可读性。下面给出的代码 sn-p 显示了使用 Method 或 Fluent LINQ 语法的解决方案之一。

              string[,] arrayOfMessages = new string[3, 2] { { "Col1","I am message 1" }, { "Col2", "I am message 2" }, { "Col3", "I am message 3" } };
              var result = arrayOfMessages.Cast<string>()
                                          .Where((msg, index) => index % 2 > 0);
              
              foreach (var msg in result)
              {
                  Console.WriteLine(msg);
              }
              

              LINQ 扩展方法不适用于多维数组,因为它们没有实现IEnumerable&lt;T&gt; 接口。这就是Cast&lt;T&gt; 出现的地方。它基本上将整个数组转换为IEnumerable&lt;T&gt;。在我们的例子中,它将多维数组展平为IEnumerable&lt;string&gt;,类似于:

              { "Col1", "I am message 1", "Col2", "I am message 2", "Col3", "I am message 3" }
              

              您也可以使用OfType&lt;T&gt; 代替Cast&lt;T&gt;。它们之间的唯一区别是,对于混合数据类型的集合,OfType&lt;T&gt; 会忽略它无法转换的值,Cast&lt;T&gt; 将抛出 InValidCastException。

              接下来,我们需要做的就是应用一个忽略(或过滤掉)偶数索引处的值的 LINQ 运算符。所以我们使用Where 运算符的重载,其Func 委托的类型为Func&lt;TSource, int, bool&gt;,其中TSource 是集合中的每个项目,int 是集合中项目的索引,bool 是返回类型。

              在上面的 sn-p 中,我使用了一个 lambda 表达式,它计算每个项目的索引,只有当它是奇数时才返回 true。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2013-08-15
                • 1970-01-01
                • 2013-04-01
                相关资源
                最近更新 更多