Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/317.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用嵌套的Foreach语句迭代多维数组_C#_Foreach_Nested Loops - Fatal编程技术网

C# 使用嵌套的Foreach语句迭代多维数组

C# 使用嵌套的Foreach语句迭代多维数组,c#,foreach,nested-loops,C#,Foreach,Nested Loops,我想这可能是一个相当简单的问题,但我还没能弄明白。如果我有这样一个二维数组: int[,] array = new int[2,3] { {1, 2, 3}, {4, 5, 6} }; 使用嵌套的foreach语句遍历数组的每个维度的最佳方法是什么 对于多维数组,可以使用相同的方法迭代元素,例如: int[,] numbers2D = new int[3, 2] { { 9, 99 }, { 3, 33 }, { 5, 55 } }; foreach (int i in numbers2D)

我想这可能是一个相当简单的问题,但我还没能弄明白。如果我有这样一个二维数组:

int[,] array = new int[2,3] { {1, 2, 3}, {4, 5, 6} };
使用嵌套的foreach语句遍历数组的每个维度的最佳方法是什么

对于多维数组,可以使用相同的方法迭代元素,例如:

int[,] numbers2D = new int[3, 2] { { 9, 99 }, { 3, 33 }, { 5, 55 } };
foreach (int i in numbers2D)
{
    System.Console.Write("{0} ", i);
}
此示例的输出为:

9 99 3 33 5 55
工具书类

在Java中,多维数组是数组的数组,因此以下方法可以工作:

    int[][] table = {
            { 1, 2, 3 },
            { 4, 5, 6 },
    };
    for (int[] row : table) {
        for (int el : row) {
            System.out.println(el);
        }
    }

下面是如何访问二维数组中的每个元素。这就是你要找的吗

for (int i=0;i<array.GetLength(0);i++)
{
    for (int j=0;j<array.GetLength(1);j++)
    {
        int cell = array[i,j];
    }
}
for(int i=0;iC#中的2D数组不适合嵌套的foreach,它不是锯齿数组(数组数组数组)的等价物。使用foreach可以执行类似操作

foreach (int i in Enumerable.Range(0, array.GetLength(0)))
    foreach (int j in Enumerable.Range(0, array.GetLength(1)))
        Console.WriteLine(array[i, j]);
但是您仍然可以使用i和j作为数组的索引值。如果您只选择garden variety
for
循环,则可读性将得到更好的保护。

两种方法:

  • 将数组定义为锯齿状数组,并使用嵌套的foreach
  • 通常定义数组,并在整个过程中使用foreach
  • #2的示例:


    输出将是1234。即,与从0到n执行i和从0到n执行j完全相同。

    如果要像展开数组一样迭代数组中的每个项,可以执行以下操作:

    foreach (int i in array) {
        Console.Write(i);
    }
    
    哪个会打印

    123456

    如果您还想知道x和y索引,则需要执行以下操作:

    for (int x = 0; x < array.GetLength(0); x += 1) {
        for (int y = 0; y < array.GetLength(1); y += 1) {
            Console.Write(array[x, y]);
        }
    }
    

    int[][]array=newint[2][{newint[3]{1,2,3},newint[3]{4,5,6};
    对于(int j=0;j
    您也可以使用枚举数。任何维度的每种数组类型都支持array.GetEnumerator方法。唯一需要注意的是,您必须处理装箱/取消装箱。但是,您需要编写的代码将非常简单

    以下是示例代码:

    class Program
    {
        static void Main(string[] args)
        {
            int[,] myArray = new int[,] { { 1, 2 }, { 3, 4 }, { 5, 6 } };
            var e = myArray.GetEnumerator();
    
            e.Reset();
    
            while (e.MoveNext())
            {
                // this will output each number from 1 to 6. 
                Console.WriteLine(e.Current.ToString());
            }
    
            Console.ReadLine();
        }
    }
    

    我知道这是一篇老文章,但我是通过谷歌找到的,玩过之后我觉得我有了一个更简单的解决方案。如果我错了,请指出,‘因为我想知道,但这至少对我的目的有用(这是基于ICR的回复):

    for(int x=0;x
    由于这两个维度都是有限的,任何一个都可以是简单的数字,从而避免嵌套的for循环。我承认我是C#的新手,所以请告诉我,如果有理由不这样做,请告诉我…

    int[,]arr={
    
    int[,] arr =  { 
                    {1, 2, 3},
                    {4, 5, 6},
                    {7, 8, 9}
                  };
     for(int i = 0; i < arr.GetLength(0); i++){
          for (int j = 0; j < arr.GetLength(1); j++)
               Console.Write( "{0}\t",arr[i, j]);
          Console.WriteLine();
        }
    
    output:  1  2  3
             4  5  6
             7  8  9
    
    {1, 2, 3}, {4, 5, 6}, {7, 8, 9} }; for(int i=0;i
    正如其他地方提到的,您可以在数组上迭代,它将在所有维度上按顺序生成所有结果。但是,如果您也想知道索引,那么使用以下方法如何-

    然后做一些类似的事情:

    var dimensionLengthRanges = Enumerable.Range(0, myArray.Rank).Select(x => Enumerable.Range(0, myArray.GetLength(x)));
    var indicesCombinations = dimensionLengthRanges.CartesianProduct();
    
    foreach (var indices in indicesCombinations)
    {
        Console.WriteLine("[{0}] = {1}", string.Join(",", indices), myArray.GetValue(indices.ToArray()));
    }
    

    您可以使用如下扩展方法:

    internal static class ArrayExt
    {
        public static IEnumerable<int> Indices(this Array array, int dimension)
        {
            for (var i = array.GetLowerBound(dimension); i <= array.GetUpperBound(dimension); i++)
            {
                yield return i;
            }
        }
    }
    
    int[,] array = { { 1, 2, 3 }, { 4, 5, 6 } };
    for (var i = array.GetLowerBound(0); i <= array.GetUpperBound(0); i++)
    {
        for (var j= array.GetLowerBound(1); j <= array.GetUpperBound(1); j++)
        {
            Console.Write(array[i, j]);
        }
    
        Console.WriteLine();
    }
    
    这将比使用for循环慢一点,但在大多数情况下可能不是问题。不确定它是否使事情更可读

    请注意,c#数组可以不是基于零的,因此可以使用如下的for循环:

    internal static class ArrayExt
    {
        public static IEnumerable<int> Indices(this Array array, int dimension)
        {
            for (var i = array.GetLowerBound(dimension); i <= array.GetUpperBound(dimension); i++)
            {
                yield return i;
            }
        }
    }
    
    int[,] array = { { 1, 2, 3 }, { 4, 5, 6 } };
    for (var i = array.GetLowerBound(0); i <= array.GetUpperBound(0); i++)
    {
        for (var j= array.GetLowerBound(1); j <= array.GetUpperBound(1); j++)
        {
            Console.Write(array[i, j]);
        }
    
        Console.WriteLine();
    }
    
    int[,]array={{1,2,3},{4,5,6};
    对于(var i=array.GetLowerBound(0);i使用LINQ
    .Cast()
    将2D数组转换为
    IEnumerable

    LINQPad示例:

    var arr = new int[,] { 
      { 1, 2, 3 }, 
      { 4, 5, 6 } 
    };
    
    IEnumerable<int> values = arr.Cast<int>();
    Console.WriteLine(values);
    
    var arr=newint[,]{
    { 1, 2, 3 }, 
    { 4, 5, 6 } 
    };
    IEnumerable values=arr.Cast();
    控制台写入线(值);
    
    输出:


    我一直在寻找一种解决方案,可以在编译时枚举一个未知的数组,并访问每个元素索引集。我看到的解决方案都有收益,但这里有另一个没有收益的实现。它采用的是老式的极简方式。在本例中,AppendArrayDebug()只需将所有元素打印到StringBuilder缓冲区

    public static void AppendArrayDebug ( StringBuilder sb, Array array )
    {
        if( array == null || array.Length == 0 )
        {
            sb.Append( "<nothing>" );
            return;
        }
    
        int i;
    
        var rank = array.Rank;
        var lastIndex = rank - 1;
    
        // Initialize indices and their boundaries
        var indices = new int[rank];
        var lower = new int[rank];
        var upper = new int[rank];
        for( i = 0; i < rank; ++i )
        {
            indices[i] = lower[i] = array.GetLowerBound( i );
            upper[i] = array.GetUpperBound( i );
        }
    
        while( true )
        {
            BeginMainLoop:
    
            // Begin work with an element
    
            var element = array.GetValue( indices );
    
            sb.AppendLine();
            sb.Append( '[' );
            for( i = 0; i < rank; ++i )
            {
                sb.Append( indices[i] );
                sb.Append( ' ' );
            }
            sb.Length -= 1;
            sb.Append( "] = " );
            sb.Append( element );
    
            // End work with the element
    
            // Increment index set
    
            // All indices except the first one are enumerated several times
            for( i = lastIndex; i > 0; )
            {
                if( ++indices[i] <= upper[i] )
                    goto BeginMainLoop;
                indices[i] = lower[i];
                --i;
            }
    
            // Special case for the first index, it must be enumerated only once
            if( ++indices[0] > upper[0] )
                break;
        }
    }
    

    它必须是二维数组,还是可以使用数组数组?如果可能的话,我希望foreach实现?C#将多维数组和锯齿数组作为单独的概念,其中
    int[,]
    是二维数组,而
    int[]
    是一个由数组组成的锯齿状数组,每个给定的数组不需要有相同的长度。你可以很容易地在锯齿状数组上进行foreach,但是2D数组不是相同类型的结构。无论如何,你的第二个代码片段不适合这个问题,第一个代码片段没有嵌套。这是一个经典的、简单的、可理解的代码片段的可怕变种可读取的构造。如果您的代码包含此构造,您真的需要考虑“嘿,这很有效,但是……不怎么样?”(我很清楚这在python家族中是惯用的。但是-这是C#。)@Rubys,这在python中也不是惯用的。获取索引然后使用
    []访问列表是非常不和谐的
    。直接对值进行迭代是惯用的Python。还要注意,Python中没有多维数组或列表(只有锯齿状)。@Matthew:我可能把Python与另一种语言混淆了,我在脚本家族中不太了解我的手臂和腿(我想这就是我在Python家族中的意思)在看到我的错误后(例如,尝试使用像锯齿状阵列一样的2D阵列),我同意遍历该列表的最佳方法就像你在第一个示例中所做的那样。你之所以获得投票,是因为你愿意超越答案并给出其他选择。为什么二维数组会变平?C#=它总是有效。C++=在浪费一些时间之前不会起作用。这是假设第二维度的长度。你是哈尔D编码假定se
    int[,] array = { { 1, 2, 3 }, { 4, 5, 6 } };
    for (var i = array.GetLowerBound(0); i <= array.GetUpperBound(0); i++)
    {
        for (var j= array.GetLowerBound(1); j <= array.GetUpperBound(1); j++)
        {
            Console.Write(array[i, j]);
        }
    
        Console.WriteLine();
    }
    
    var arr = new int[,] { 
      { 1, 2, 3 }, 
      { 4, 5, 6 } 
    };
    
    IEnumerable<int> values = arr.Cast<int>();
    Console.WriteLine(values);
    
    public static void AppendArrayDebug ( StringBuilder sb, Array array )
    {
        if( array == null || array.Length == 0 )
        {
            sb.Append( "<nothing>" );
            return;
        }
    
        int i;
    
        var rank = array.Rank;
        var lastIndex = rank - 1;
    
        // Initialize indices and their boundaries
        var indices = new int[rank];
        var lower = new int[rank];
        var upper = new int[rank];
        for( i = 0; i < rank; ++i )
        {
            indices[i] = lower[i] = array.GetLowerBound( i );
            upper[i] = array.GetUpperBound( i );
        }
    
        while( true )
        {
            BeginMainLoop:
    
            // Begin work with an element
    
            var element = array.GetValue( indices );
    
            sb.AppendLine();
            sb.Append( '[' );
            for( i = 0; i < rank; ++i )
            {
                sb.Append( indices[i] );
                sb.Append( ' ' );
            }
            sb.Length -= 1;
            sb.Append( "] = " );
            sb.Append( element );
    
            // End work with the element
    
            // Increment index set
    
            // All indices except the first one are enumerated several times
            for( i = lastIndex; i > 0; )
            {
                if( ++indices[i] <= upper[i] )
                    goto BeginMainLoop;
                indices[i] = lower[i];
                --i;
            }
    
            // Special case for the first index, it must be enumerated only once
            if( ++indices[0] > upper[0] )
                break;
        }
    }
    
    var array = new [,,]
    {
        { {  1,  2,  3 }, {  4,  5,  6 }, {  7,  8,  9 }, { 10, 11, 12 } },
        { { 13, 14, 15 }, { 16, 17, 18 }, { 19, 20, 21 }, { 22, 23, 24 } }
    };
    
    /*
    Output:
    
    [0 0 0] = 1
    [0 0 1] = 2
    [0 0 2] = 3
    [0 1 0] = 4
    [0 1 1] = 5
    [0 1 2] = 6
    [0 2 0] = 7
    [0 2 1] = 8
    [0 2 2] = 9
    [0 3 0] = 10
    [0 3 1] = 11
    [0 3 2] = 12
    [1 0 0] = 13
    [1 0 1] = 14
    [1 0 2] = 15
    [1 1 0] = 16
    [1 1 1] = 17
    [1 1 2] = 18
    [1 2 0] = 19
    [1 2 1] = 20
    [1 2 2] = 21
    [1 3 0] = 22
    [1 3 1] = 23
    [1 3 2] = 24
    */