C# 循环遍历未知维度的数组

Posted

技术标签:

【中文标题】C# 循环遍历未知维度的数组【英文标题】:C# loop over an array of unknown dimensions 【发布时间】:2019-01-20 18:45:39 【问题描述】:

我想创建一个扩展方法来循环 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
    

我敢肯定,还有更优雅的方法可以做到这一点。但我想不通。如何将这种方法推广到无限数量的维度?

【问题讨论】:

Why do C# multidimensional arrays not implement IEnumerable<T>?的可能重复 @ChristianGollhardt 在 OOP 语言中使用多维数组有什么“根本错误”?您希望如何在没有多维数组的情况下进行张量操作? 看来我误解了你的问题。我把尺寸误认为是尺寸的大小。 @koryakinp 【参考方案1】:

您可以尝试递归方法,测试数组中的项目本身是否为数组。如果项目是可迭代的,则将调用 for 循环逻辑,否则您可以对项目进行任何您需要做的操作。如果您的对象实现了 ICollection,这应该相当简单。

【讨论】:

我认为 zcleghern 的意思类似于 ``` public static void ForEach(this Array source, Action action) if (source.Rank == 0) foreach (var item在源)动作((T)项目); else foreach (Array arr in source) arr.ForEach(action); ```【参考方案2】:

如果您不关心索引,则可以在完全不知道其排名的情况下迭代 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

【讨论】:

【参考方案3】:

对于那些在家玩的人来说,这有点乱,但可以让你利用yield 超过一个等级foreach

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

【讨论】:

以上是关于C# 循环遍历未知维度的数组的主要内容,如果未能解决你的问题,请参考以下文章

循环遍历一个大数组并将值加在一起 ​​C#

c#如何遍历一个list将值传到数组

c#用foreach遍历数组、列表时是直接获得数据元素,而foreach哈希表时,为啥获得的是命名空间名??

C#中如何用for循环遍历List<类>?

SystemVerilog foreach 语法,用于循环遍历多维数组的低维

c# for循环效率问题,遍历list<string>集合;