C#遍历未知尺寸的数组

时间:2018-08-14 01:13:34

标签: c# loops multidimensional-array system.array

我想创建一个扩展方法,以在尺寸未知的System.Array上循环

目前,我使用的是幼稚的方法:

public static void ForEach<T>(this Array source, Action<T> action)
{
    if(source.Rank == 1)
    {
        for (int w = 0; w < source.GetLength(0); w++)
        {
            action((T)source.GetValue(w));
        }
    }
    else if(source.Rank == 2)
    {
        for (int h = 0; h < source.GetLength(1); h++)
        {
            for (int w = 0; w < source.GetLength(0); w++)
            {
                action((T)source.GetValue(h, w));
            }
        }
    }
    else if(source.Rank == 3)
    {
        // etc
    }
}

我敢肯定,这样做的方式要优雅得多。但是我无法弄清楚。如何将这种方法推广到无数个维度?

3 个答案:

答案 0 :(得分:1)

如果您不关心索引,则可以完全不知道其排名来遍历System.Array。枚举器将击中每个元素。

public class Program
{
    public static void IterateOverArray(System.Array a)
    {
        foreach (var i in a)
        {
            Console.WriteLine(i);
        }
    }

    public static void Main()
    {
        var tests = new System.Array []
        {
            new int[] {1,2,3,4,5,6,7,8},
            new int[,]
            {
                {1,2},{3,4},{5,6},{7,8}
            },
            new int[,,]
            {
                {  {1,2},{3,4} },
                {  {5,6},{7,8} }
            }
        };


        foreach (var t in tests)
        {
            Console.WriteLine("Dumping array with rank {0} to console.", t.Rank);
            IterateOverArray(t);
        }
    }
}

输出:

Dumping array with rank 1 to console.
1
2
3
4
5
6
7
8
Dumping array with rank 2 to console.
1
2
3
4
5
6
7
8
Dumping array with rank 3 to console.
1
2
3
4
5
6
7
8

Link to DotNetFiddle example

答案 1 :(得分:1)

对于那些在家中玩耍的人来说,这有点混乱,但是可以利用foreach

来排名yield
public static IEnumerable<T> GetRank<T>(this Array source,int dimension, params int[] indexes )
{

   var indexList = indexes.ToList();
   indexList.Insert(dimension, 0);
   indexes = indexList.ToArray();

   for (var i = 0; i < source.GetLength(dimension); i++)
   {
      indexes[dimension] = i;
      yield return (T)source.GetValue(indexes);
   }
}

用法

var test1 = new int[2, 2, 3];
test1[1, 1, 0] = 1;
test1[1, 1, 1] = 2;
test1[1, 1, 2] = 3;
foreach (var item in test1.GetRank<int>(2,1,1))
{
  Console.WriteLine(item);
}

输出

1
2
3

Full demo here

答案 2 :(得分:-1)

您可以尝试一种递归方法,在该方法中,测试数组中的项本身是否是数组。如果项目是可迭代的,则将调用for循环逻辑,否则,您可以根据需要执行该操作。如果您的对象实现了ICollection,那么这应该非常简单。