14

ギザギザの配列ではなく、長方形の文字列配列があるとします

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

これから1次元配列(単一行または単一列)を抽出する最良の方法は何ですか? もちろん、これは for ループで実行できますが、.NET にもっと洗練された方法が組み込まれていることを願っています。

抽出された文字列配列をオブジェクト配列に変換するためのボーナス ポイント。

4

6 に答える 6

13

文字列配列をオブジェクト配列に簡単にキャストできます。他の方法では機能しません。ただし、実際の抽出でfor ループを使用する必要がありますが、私が見る限りArray.Copy、ソースとターゲットのランクが同じである必要があり、Buffer.BlockCopy値型の配列に対してのみ機能します。奇妙に思えますが...

LINQ を使用して 1 つのステートメントで行または列を追加できますが、非効率的ですが (リストを内部で構築し、それを配列に変換する必要があるため、自分で行う場合は配列を事前に割り当てることができます)。適切なサイズに変更して直接コピーします)。

行のコピー (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メソッドとメソッドを作成ExtractColumnして再利用する場合はそうです。

于 2008-10-24T05:30:32.803 に答える
8

矩形配列の場合:

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();
于 2008-10-24T13:15:41.557 に答える
4

明確にしたいと思います(例と何が求められているかを考えれば)。

ジャグ配列は配列の配列であり、次のように宣言されます。

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]" };

複数の次元を保持する単一の配列として定義されている長方形の配列とは異なります。

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

このため、ギザギザの配列はIQueryable / IEnumerableです。これは、反復するたびに配列を受け取るように反復できるためです。要素は全次元(0,0 0,1..etc)でアドレス指定されるため、長方形配列はIQueryable / IEnumerableではないため、その場合、LinqまたはArray用に作成された事前定義された関数を使用することはできません。

次のように、配列を1回繰り返すことができます(そして必要なことを達成できます)。

/// 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;

お役に立てれば :)

于 2008-10-24T06:42:51.267 に答える
1

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

これにより、最初の行が単一のディメンション配列にコピーされます。

于 2008-10-24T09:04:25.133 に答える
1

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++;
    }
}
于 2008-10-24T05:24:53.483 に答える
0

拡張方法を作りました。私はパフォーマンスについて知りません。

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) ; 
于 2015-12-30T08:27:02.730 に答える