Domanda

ho incontrato un problema in cui mi piacerebbe creare una tabella Array. Che è un array bidimensionale 2 dove il numero di righe e colonne sono noti a runtime prima della tabella deve essere creata. Il numero di colonne è lo stesso per tutte le righe.

Una volta che l'array è stato creato vorrei operare su solo 1 dimensione di quella matrice. Forse passare un riferimento ad un metodo.

Ecco un esempio fittizio:

// Create a table 3x3 table.
int[,] DistanceTable = new int[3, 3];
DistanceTable[0, 0] = 0;
DistanceTable[1, 1] = 0;
DistanceTable[2, 2] = 0;

DistanceTable[0, 1] = 10;
DistanceTable[0, 2] = 40;

DistanceTable[1, 0] = 10;
DistanceTable[1, 2] = 25;

DistanceTable[2, 0] = 40;
DistanceTable[2, 1] = 25;

// Why can't I do this?
int[] twos = DistanceTable[2];

Se dovessi usare un JaggedArray (Array-of-Array) che mi permette di fare questo. Ma io non ho bisogno di JaggedArray perché la mia matrice multidemsional ha sempre lo stesso numero di colonne per ogni riga.

E 'possibile fare questo? Se no perché?

Grazie

È stato utile?

Soluzione

No. array multidimensionali differiscono dalle matrici dentellati dal fatto che sono memorizzati sequenzialmente, in un blocco di memoria, utilizzando Row-Major ordinazione .

A causa di questo, tirando fuori una "colonna" dei dati richiede saltare per tirare fuori questo.

array frastagliati, d'altro canto, sono un array di riferimenti ad una seconda matrice. Ciò rende facile estrarre singoli "array" dalla matrice irregolare.

  

Ma non ho bisogno di un JaggedArray perché la mia matrice multidemsional ha sempre lo stesso numero di colonne per ogni riga.

Jagged array in .NET ha grossi ottimizzazioni delle prestazioni. Spesso outperform array multidimensionali. Questo è il motivo per cui la maggior parte delle routine di analisi del codice suggeriranno conversione ad una matrice irregolare da un array bidimensionale. Sarebbe opportuno prendere in considerazione questo, anche se non lo fai "bisogno" di esso.

Altri suggerimenti

Questo non è possibile; array multidimensionali non funzionano in questo modo.

In generale, è necessario utilizzare sempre gli array frastagliati; sono più veloci.
(Il jitter genererà istruzioni di accesso alla memoria cruda, invece di chiamate di metodo)

C'è solo oggetto array con un array multidimensionale mentre un una matrice irregolare è un raggruppamento di più distinti oggetti array. Non c'è un 1-1 match-up o metodo di estrazione (che non comporta usando un avvolgimento).

Mi dispiace, questo dovrebbe davvero essere un commento a Come faccio a ottenere un riferimento a una sola dimensione di un array multidemensional in C #? ma io non sono autorizzato a commentare ancora. .

In ogni caso, la ragione per cui la performance è migliore con una matrice irregolare è facile da capire, dopo qualche spiegazione: esaminiamo un array multidimensionale:

{{0, 1, 2},  {3, 4, 5},  {6, 7, 8}}

In memoria è memorizzato qualcosa di simile:. {0, 1, 2, 3, 4, 5, 6, 7, 8}

Ora, supponiamo che si desidera accedere [0, 0], in cui nella memoria stiamo andando a leggere? Dobbiamo calcolare l'indirizzo: y * 3 + x => 0 * 3 + 0 => 0. Dopo di che, siamo in grado di andare avanti e fare la lettura vera e propria. Nel caso in cui vogliamo leggere l'intera linea, dobbiamo fare questo per la matematica più e più volte.

qualcosa invece un'occhiata a una matrice irregolare, in memoria è immagazzinata in questo modo:

A: {0, 1, 2} B: {3, 4, 5} C: {6, 7, 8} {Ref: una, ref: B, ref: c}

Supponiamo di voler accedere [0] [0], in cui nella memoria stiamo andando a leggere? In primo luogo, cerchiamo di ottenere un riferimento al array [0]. E quindi ottenere il contenuto della cella di [0]. Fatto. Nel caso in cui vogliamo leggere l'intera linea, abbiamo solo bisogno di incrementare il puntatore per uno.

Se vogliamo per scorrere l'intero "matrice" invece di una riga, è ancora lo stesso beneficio prestazioni per array frastagliati.

C'è una sola eccezione però: colonne iterazione. Questo è davvero un male per gli array frastagliati dato che stiamo andando a fare un parente costoso di memoria lettura obbligata per ogni singolo accesso. Non va bene.

Se si ritiene che si tratta di un problema non c'è un metodo di sinistra: un array monodimensionale! In questo caso si usa la teoria dietro l'array multidimensionale (y * righe a lunghezza + x), e utilizzare alcuni molto semplici calcoli; Per iterate consecutive: solo incrementano di uno, ad un'iterazione una colonna:. Semplicemente incrementando di righe a lunghezza

Si potrebbe fare un metodo di estensione sul vostro oggetto DictionaryTable che consente di specificare la riga?

public static class IntArrayExt
{
    public static int[] Row(this int[,] array, int row)
    {
        int[] newArray = new int[3];
        for (int i = 0; i < array.Length; i++)
        {
            newArray[i] = array[row, i];
        }
        return newArray;
    }
}

int[,] distanceTable = new int[3, 3];
distanceTable[0, 0] = 0;
distanceTable[1, 1] = 0;
distanceTable[2, 2] = 0;

distanceTable[0, 1] = 10;
distanceTable[0, 2] = 40;

distanceTable[1, 0] = 10;
distanceTable[1, 2] = 25;

distanceTable[2, 0] = 40;
distanceTable[2, 1] = 25;

int[] twos = distanceTable.Row(2);

Si potrebbe fare un altro metodo di estensione, se si vuole ottenere una colonna.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top