C#의 직사각형 배열에서 1 차원 배열을 추출하는 가장 좋은 방법은 무엇입니까?

StackOverflow https://stackoverflow.com/questions/232545

  •  04-07-2019
  •  | 
  •  

문제

직사각형 문자열 배열이 있다고 말합니다 - 들쭉날쭉 한 배열이 아닙니다.

string[,] strings = new string[8, 3];

이것 (단일 행 또는 단일 열)에서 1 차원 배열을 추출하는 가장 좋은 방법은 무엇입니까? 물론 For Loop 으로이 작업을 수행 할 수 있지만 .NET은 더 우아한 방식으로 내장되어 있기를 바라고 있습니다.

추출 된 문자열 배열을 객체 배열로 변환하기위한 보너스 포인트.

도움이 되었습니까?

해결책

직사각형 배열 :

string[,] rectArray = new string[3,3] { 
    {"a", "b", "c"}, 
    {"d", "e", "f"}, 
    {"g", "h", "i"} };

var rectResult = rectArray.Cast<object>().ToArray();

그리고 들쭉날쭉 한 배열의 경우 :

string[][] jaggedArray =  { 
    new string[] {"a", "b", "c", "d"}, 
    new string[] {"e", "f"}, 
    new string[] {"g", "h", "i"} };

var jaggedResult = jaggedArray.SelectMany(s => s).Cast<object>().ToArray();

다른 팁

문자열 배열을 객체 배열에 사소하게 시전 할 수 있습니다. 다른 방식으로가는 것은 작동하지 않습니다. 실제 추출 가지다 내가 볼 수있는 한, 루프 용을 사용하려면 : Array.Copy 소스와 대상 순위가 동일해야하며 Buffer.BlockCopy 값 유형 배열에만 작동합니다. 그래도 이상해 보인다 ...

비효율적이지만 (내부적으로 목록을 작성하고 배열로 변환해야하므로 직접 할 수 있다면 배열을 Prealloce로 할 수 있습니다. 올바른 크기로 직접 복사).

행 복사 (rowNum 복사 할 행) : :

object[] row = Enumerable.Range(0, rowLength)
                         .Select(colNum => (object) stringArray[rowNum, colNum])
                         .ToArray();

열 복사 (colNum 복사 할 열) : :

object[] column = Enumerable.Range(0, columnLength)
                            .Select(rowNum => (object) stringArray[rowNum, colNum])
                            .ToArray();

나는 이것이 Foreach 루프보다 더 나은/단순한 지 확실하지 않습니다. 특히 당신이 ExtractRow 방법과 an ExtractColumn 방법과 재사용.

나는 그냥 명확히하고 싶습니다 (예와 무엇을 요청하는지).

들쭉날쭉 한 배열 배열 배열이며 다음과 같이 선언됩니다.

string[][] data = new string[3][];
data[0] = new string[] { "0,[0]", "0,[1]", "0,[2]" };
data[1] = new string[] { "1,[0]", "1,[1]", "1,[2]" ];
data[2] = new string[] { "2,[0]", "1,[1]", "1,[2]" };

대 a 직사각형 배열 여러 차원을 보유하는 단일 배열로 정의됩니다.

string[,] data = new string[3,3];
data[0,0] = "0,0";
data[0,1] = "0,1";
data[0,2] = "0,2";
...etc

이 때문에 a 들쭉날쭉 한 배열 각 반복 할 때 배열을 받기 위해 반복 할 수 있기 때문에 iqueryable/ienumerable입니다. 반면 a 직사각형 배열 ~이다 ~ 아니다 요소가 전체 차원 (0,0 0,1..etc)으로 주소되므로 IQueryable/Ienumerable이므로 LINQ 또는이 경우 배열에 대해 생성 된 사전 정의 된 함수를 사용할 수 없습니다.

이렇게 배열을 한 번 반복 할 수 있습니다.

/// INPUT: rowIndex, OUTPUT: An object[] of data for that row
int colLength = stringArray.GetLength(1);
object[] rowData = new object[colLength];
for (int col = 0; col < colLength; col++) {
    rowData[col] = stringArray[rowIndex, col] as object;
}
return rowData;

/// INPUT: colIndex, OUTPUT: An object[] of data for that column
int rowLength = stringArray.GetLength(0);
object[] colData = new object[rowLength];
for (int row = 0; r < rowLength; row++) {
    colData[row] = stringArray[row, colIndex] as object;
}
return colData;

도움이 되었기를 바랍니다 :)

LINQ가 답입니다

static object[] GetColumn(string[][] source, int col) {
    return source.Iterate().Select(x => source[x.Index][col]).Cast<object>().ToArray();
}
static object[] GetRow(string[][] source, int row) {
    return source.Skip(row).First().Cast<object>().ToArray();
}
public class Pair<T> {
    public int Index;
    public T Value;
    public Pair(int i, T v) {
        Index = i;
        Value = v;
    }
}
static IEnumerable<Pair<T>> Iterate<T>(this IEnumerable<T> source) {
    int index = 0;
    foreach (var cur in source) {
        yield return new Pair<T>(index, cur);
        index++;
    }
}

Array.copy를 사용하여 행을 쉽게 복사 할 수 있습니다.

        int[][] arDouble = new int[2][];
        arDouble[0] = new int[2];
        arDouble[1] = new int[2];
        arDouble[0][0] = 1;
        arDouble[0][1] = 2;
        arDouble[1][0] = 3;
        arDouble[1][1] = 4;

        int[] arSingle = new int[arDouble[0].Length];

        Array.Copy(arDouble[0], arSingle, arDouble[0].Length);

첫 번째 행을 단일 치수 배열로 복사합니다.

나는 확장 방법을 만들었다. 나는 성능에 대해 모른다.

public static class ExtensionMethods 
{
     public static string[] get1Dim(this string[,] RectArr, int _1DimIndex , int _2DimIndex   )
     {
        string[] temp = new string[RectArr.GetLength(1)];

        if (_2DimIndex == -1)
        {
          for (int i = 0; i < RectArr.GetLength(1); i++)
          {   temp[i] = RectArr[_1DimIndex, i];    }
        }
        else
        {
          for (int i = 0; i < RectArr.GetLength(0); i++)
          {   temp[i] = RectArr[  i , _2DimIndex];    }
        }

         return temp;
      }
}

용법

// we now have this funtionaliy RectArray[1, * ]  
//                                       -1 means ALL    
string[] _1stRow = RectArray.get1Dim( 0, -1) ;    
string[] _2ndRow = RectArray.get1Dim( 1, -1) ; 

string[] _1stCol = RectArray.get1Dim( -1, 0) ;    
string[] _2ndCol = RectArray.get1Dim( -1, 1) ; 
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top