중첩 된 Foreach 문을 사용하여 다차원 배열 반복


79

꽤 간단한 질문이라고 생각하지만 아직 알아낼 ​​수 없었습니다. 다음과 같은 2 차원 배열이있는 경우 :

int[,] array = new int[2,3] { {1, 2, 3}, {4, 5, 6} };

중첩 된 foreach 문 을 사용하여 배열의 각 차원을 반복하는 가장 좋은 방법은 무엇입니까 ?


2 차원 배열이어야합니까, 아니면 배열 배열을 사용할 수 있습니까?
Matthew Flaschen

답변:


133

평면화 된 배열 인 것처럼 배열의 모든 항목을 반복하려면 다음을 수행하면됩니다.

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 = new int[2][] { new int[3] {1, 2, 3}, new int[3] {4, 5, 6} };
foreach (int[] subArray in array) {
    foreach (int i in subArray) {
        Console.Write(i);
    }
}

또는

int[][] array = new int[2][] { new int[3] {1, 2, 3}, new int[3] {4, 5, 6} };
for (int j = 0; j < array.Length; j += 1) {
    for (int k = 0; k < array[j].Length; k += 1) {
        Console.Write(array[j][k]);
    }
}

1
내 방식의 오류를 확인한 후 (예 : 들쭉날쭉 한 배열과 같은 2D 배열을 사용하려는 시도), 해당 목록을 반복하는 가장 좋은 방법은 첫 번째 예제에서와 같은 방법이라는 데 동의합니다. 답변을 넘어서 다른 옵션을 제공하려는 의지 때문에 투표를 받게됩니다.
Tyler Murry

2 차원 배열이 평면화되는 이유는 무엇입니까?
Sipo

C # = 항상 작동합니다. C ++ = 시간을 낭비하기 전에는 작동하지 않습니다.
jw_

21

2 차원 배열의 각 요소를 방문하는 방법은 다음과 같습니다. 이것이 당신이 찾던 것입니까?

for (int i=0;i<array.GetLength(0);i++)
{
    for (int j=0;j<array.GetLength(1);j++)
    {
        int cell = array[i,j];
    }
}

1
가능하다면 foreach 구현 을 기대하고 있었습니까?
Tyler Murry

6

다차원 배열을 사용하면 동일한 방법을 사용하여 요소를 반복 할 수 있습니다. 예를 들면 다음과 같습니다.

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);
        }
    }

3
C #에는 다차원 및 들쭉날쭉 한 배열이 별도의 개념으로 있습니다. 여기서는 int[,]2 차원 배열이고 int[][]들쭉날쭉 한 배열 배열이며 지정된 각 배열의 길이가 같을 필요는 없습니다. 들쭉날쭉 한 배열에서 foreach를 쉽게 수행 할 수 있지만 2D 배열은 동일한 유형의 구조가 아닙니다. 어쨌든 두 번째 스 니펫은 문제에 맞지 않으며 첫 번째 스 니펫은 중첩되지 않습니다.
Anthony Pegram

4

나는 이것이 오래된 게시물이라는 것을 알고 있지만 Google을 통해 발견했으며 그것을 가지고 노는 후에 더 쉬운 해결책이 있다고 생각합니다. 내가 틀렸다면 '알고 싶습니다만, 이것은 적어도 내 목적을 위해 작동했습니다 (ICR의 응답을 기반으로 함).

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

두 차원이 모두 제한되어 있으므로 둘 중 하나는 단순한 숫자 일 수 있으므로 중첩 된 for 루프를 피하십시오. 저는 C #을 처음 접했음을 인정합니다. 그러니하지 말아야 할 이유가 있으면 알려주세요 ...


1
이것은 2 차원의 길이를 가정합니다. 두 번째 차원의 길이는 항상 3이라는 가정을 하드 코딩하고 있는데, 그렇지 않을 수도 있습니다. 3 개가 아니라 50 개라면 복사 / 붙여 넣기를 많이해서 코드를 읽을 수 없게 만들 것입니다. :)
Adam Lear

@AnnaLear 가정이 반드시 잘못된 것은 아닙니다. 15x15 스크래블 보드와 같이 잘 정의 된 길이의 행렬을 처리하고있을 수 있습니다
Jaycee

3

C #의 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를 배열의 인덱스 값으로 사용합니다. for대신 가든 버라이어티 루프에 가면 가독성이 더 잘 보존 됩니다.


1
이것은 고전적이고 단순하며 이해하기 쉬운 구조의 끔찍한 변형입니다. 코드에이 내용이 포함되어 있으면 "이건 작동하지만 ... 안되는 건 어때?"라고 생각해야합니다. (나는 이것이 파이썬 계열에서 관용적이라는 것을 잘 알고 있습니다. 그러나 이것은 C #입니다.)
Rubys

@Rubys, 이것은 파이썬에서도 관용적이지 않습니다. 인덱스를 얻은 다음 []. 값을 직접 반복하는 것은 관용적 인 Python입니다. 또한 파이썬에는 다차원 배열이나 목록이 없다는 점에 유의하십시오 (단지 톱니 모양 만 있음).
Matthew Flaschen

@Matthew : 파이썬을 다른 언어와 혼동했을 수 있습니다. 스크립팅 제품군의 내 다리에서 내 팔을 실제로 알지 못합니다 (파이썬 제품군에서 의미하는
바입니다

2

두 가지 방법:

  1. 배열을 들쭉날쭉 한 배열로 정의하고 중첩 된 foreach를 사용합니다.
  2. 배열을 정상적으로 정의하고 전체에 대해 foreach를 사용하십시오.

# 2의 예 :

int[,] arr = { { 1, 2 }, { 3, 4 } };
foreach(int a in arr)
    Console.Write(a);

출력은 1234입니다. 즉. i를 0에서 n으로, j를 0에서 n으로하는 것과 똑같습니다.


2

다음과 같은 확장 방법을 사용할 수 있습니다.

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 } };
foreach (var i in array.Indices(0))
{
    foreach (var j in array.Indices(1))
    {
        Console.Write(array[i, j]);
    }

    Console.WriteLine();
}

for 루프를 사용하는 것보다 약간 느리지 만 대부분의 경우 문제가되지 않습니다. 더 읽기 쉽게 만드는지 확실하지 않습니다.

C # 배열은 0부터 시작하지 않을 수 있으므로 다음과 같이 for 루프를 사용할 수 있습니다.

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();
}

이상하다 ... 무엇이 제로 기반이 아닌가?
drzaus

Excel과 상호 운용 할 때 0이 아닌 것을 본 것 같습니다. 일반적이지는 않지만 알아두면 좋을 것입니다.
요한 라르손

1

다른 곳에서 언급했듯이 배열을 반복하면 모든 차원에서 순서대로 모든 결과가 생성됩니다. 그러나 인덱스도 알고 싶다면 http://blogs.msdn.com/b/ericlippert/archive/2010/06/28/computing-a-cartesian-product-with- linq.aspx

그런 다음 다음과 같이합니다.

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()));
}

1

LINQ .Cast<int>()를 사용 하여 2D 배열을 IEnumerable<int>.

LINQPad 예 :

var arr = new int[,] { 
  { 1, 2, 3 }, 
  { 4, 5, 6 } 
};

IEnumerable<int> values = arr.Cast<int>();
Console.WriteLine(values);

산출:

시퀀스는 1,2,3,4,5,6입니다.


0

열거자를 사용할 수도 있습니다. 모든 차원의 모든 배열 유형은 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();
    }
}

투표 -1 ... 나는 msdn을 인용한다Using foreach is recommended, instead of directly manipulating the enumerator.
Ivan

0
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

0

모든 요소 인덱스 세트에 대한 액세스 권한으로 컴파일 타임 순위에서 알 수없는 배열을 열거하는 솔루션을 찾고있었습니다. 수율이있는 솔루션을 보았지만 여기에 수율이없는 또 다른 구현이 있습니다. 구식 미니멀리즘 방식입니다. 이 예제에서 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;
    }
}

예를 들어 다음 배열은 다음 출력을 생성합니다.

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
*/
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.