Was ist der beste Weg, um ein eindimensionales Array aus einem rechteckigen Feld in C # zu extrahieren?

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

  •  04-07-2019
  •  | 
  •  

Frage

Sagen, dass ich einen rechteckigen String-Array haben - nicht ein verzweigtes Array

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

Was ist der beste Weg, um eine eindimensionale Anordnung von dieser (entweder einer einzelnen Zeile oder einer Spalte) zu extrahieren? Ich kann für Schleife, natürlich mit einem dies tun, aber ich hoffe, .NET eine elegantere Art und Weise hat eingebaut.

Bonuspunkte für die extrahierte Zeichenfolge Array auf ein Objektarray umgewandelt werden.

War es hilfreich?

Lösung

Für ein rechteckiges Array:

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

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

Und für einen gezackten Array:

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

Andere Tipps

Sie können einen String-Array auf ein Objektarray werfen trivialen - in die andere Richtung funktioniert nicht. Die eigentliche Extraktion hat ein, obwohl für Schleife zu verwenden, soweit ich sehen kann: Array.Copy erfordert die Quell- und Ziel stuft das gleiche zu sein, und Buffer.BlockCopy funktioniert nur für Werttyp-Arrays. Es scheint seltsam, obwohl ...

Sie kann LINQ verwenden, um zusätzliche eine Zeile oder Spalte in einer einzigen Anweisung, obwohl es ineffizient sein wird (wie es intern eine Liste aufbauen würde, dann ist es in ein Array umwandeln müssen - wenn Sie es selbst tun können Sie preallocate das Array auf die richtige Größe und direkt kopieren).

Kopieren einer Zeile (rowNum ist die Zeile kopiert werden):

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

Kopieren einer Spalte (colNum ist die Spalte kopiert werden):

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

Ich bin nicht sicher, dass dies wirklich besser / einfacher als eine foreach-Schleife jedoch - vor allem, wenn Sie ein ExtractRow Verfahren und eine ExtractColumn Methode schreiben und wieder zu verwenden

.

ich mag nur klären (das Beispiel gegeben und was gefragt werden wird).

A gezackte array ist ein Array von Arrays und gleichen so deklariert:

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

Versus einer rechteckigen Anordnung als ein einzelnes Array definiert ist, die mehrere Dimensionen gilt:

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

Aus diesem Grunde, ein gezackte Array ist IQueryable / IEnumerable, weil man über sie laufen kann ein Array bei jeder Iteration zu empfangen. Während eine rechteckige Anordnung ist nicht IQueryable / IEnumerable weil Elemente in voller Dimension angesprochen werden (0,0 0,1..etc), so dass Sie wird nicht die Fähigkeit haben, Linq oder alle vordefinierten Funktionen für Array in diesem Fall erstellt wurde.

Auch wenn Sie über das Array iterieren kann einmal (und erreichen, was Sie wollen) wie folgt aus:

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

Hope, das hilft:)

LINQ ist die Antwort

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

Zeilen kopiert werden kann leicht Array.Copy mit:

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

Dies wird die erste Zeile in die einzige Dimension Array kopieren.

i gemacht extention Methode. Ich weiß nicht, über die Leistung.

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

Verwendung

// 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) ; 
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top