Por que temos uma matriz denteada e uma matriz multidimensional?

87
  1. Qual é a diferença entre matriz denteada e matriz multidimensional. Existe um benefício de um no outro?

  2. E por que o Visual Studio não me permite fazer um

    MyClass[][] abc = new MyClass[10][20];
    

    (Costumávamos fazer isso em C ++, mas em C # sublinha [20] com uma linha vermelha torcida. Diz especificador de classificação inválido)

    mas está feliz com

    MyClass[,] abc = new MyClass[10,20];
    
  3. Finalmente, como posso inicializar isso em uma única linha (como fazemos em array simples com {new xxx...}{new xxx....})

    MyClass[][,][,] itemscollection;
    
Shekhar_Pro
fonte
11
O ponto principal de um array irregular é que os arrays "aninhados" não precisam ter tamanho uniforme.
Ani
1
msdn.microsoft.com/en-us/library/2yd9wwz4(v=vs.71).aspx - Sintaxe de matriz multidimensional como [X, Y] é válida de acordo com docs
ndtreviv
Subquestão adicional: É possível usar foreach () com array multidimensional?
Serge Wautier
@Serge - é claro, como Arrayimplementos IEnumerable. Você pode sempre tentar e ver por si mesmo :)
thecoop

Respostas:

101
  1. Uma matriz denteada é uma matriz de matrizes, portanto an int[][]é uma matriz de int[], cada uma das quais pode ter comprimentos diferentes e ocupar seu próprio bloco na memória. Um array multidimensional ( int[,]) é um único bloco de memória (essencialmente uma matriz).

  2. Você não pode criar um MyClass[10][20]porque cada submatriz deve ser inicializada separadamente, pois são objetos separados:

    MyClass[][] abc = new MyClass[10][];
    
    for (int i=0; i<abc.Length; i++) {
        abc[i] = new MyClass[20];
    }
    

    A MyClass[10,20]está ok, porque está inicializando um único objeto como uma matriz com 10 linhas e 20 colunas.

  3. A MyClass[][,][,]pode ser inicializado assim (embora não seja testado por compilação):

    MyClass[][,][,] abc = new MyClass[10][,][,];
    
    for (int i=0; i<abc.Length; i++) {
        abc[i] = new MyClass[20,30][,];
    
        for (int j=0; j<abc[i].GetLength(0); j++) {
            for (int k=0; k<abc[i].GetLength(1); k++) {
                abc[i][j,k] = new MyClass[40,50];
            }
        }
    }
    

Lembre-se de que o CLR é altamente otimizado para acesso a uma matriz de dimensão única, portanto, usar uma matriz irregular provavelmente será mais rápido do que uma matriz multidimensional do mesmo tamanho.

theecoop
fonte
6
você pode nos apontar algumas evidências de que os acessos de matriz unidimensional são mais rápidos?
GreyCloud
Existe um caso de uso (comum) para a matriz multidimensional?
ryanwebjackson
1
Exemplos: tabuleiro xadrez var board = new Piece[8, 8];, uma matriz de transformação var m = new double[2, 2]; .
Olivier Jacot-Descombes
37

Uma matriz denteada é uma matriz de matrizes. Cada array não tem garantia de ter o mesmo tamanho. Você pode ter

int[][] jaggedArray = new int[5][];
jaggedArray[0] = new[] {1, 2, 3}; // 3 item array
jaggedArray[1] = new int[10];     // 10 item array
// etc.

É um conjunto de matrizes relacionadas.

Uma matriz multidimensional, por outro lado, é mais um agrupamento coeso, como uma caixa, mesa, cubo, etc., onde não existem comprimentos irregulares. Quer dizer

int i = array[1,10];
int j = array[2,10]; // 10 will be available at 2 if available at 1
Anthony Pegram
fonte
Tentei seu código. Ele não compilou. Tente adicionar int [3] então tente jaggedArray[0] = int[3]{ 1, 2, 3 };
barlop
Eu sei que isso é antigo, mas apenas para fins informativos int [3] não é necessário. um simples int [] é tudo o que importa. int [] [] meuVetor = novo int [5] []; meuVetor [0] = novo int [] {1, 2, 3, 4}; Isso é tudo o que é necessário.
Velocibadgery de
Você pode fazer isso para compilar em C #? Não posso compilar, a jaggedArray[0] = { 1, 2, 3 };menos que mude para = new[] { 1, 2, 3 }(ou = new int[] { 1, 2, 3 }antes de C # 3.0). De acordo com o Guia de Programação C # da Microsoft , "Você pode declarar uma variável de array sem criá-la, mas deve usar o novo operador ao atribuir um novo array a essa variável."
Joel V. Earnest-DeYoung
11

Uma matriz retangular sempre tem a mesma quantidade de colunas para cada linha.

MyClass[,] x = new MyClass[10,30]

Cada linha tem 30 colunas, enquanto em uma matriz denteada, isso não é necessário. Portanto, acho que você terá que inicializar cada 'linha' em uma matriz irregular separadamente:

MyClass[][] x = new MyClass[10][];

for(int i = 0; i < 10; i++)
{
    x[i] = new MyClass[30];
}

Na verdade, isso significa que nem todas as linhas da matriz denteada devem conter o mesmo número de elementos. (No meu exemplo, ele tem o mesmo número de elementos, mas isso não é obrigatório).

Você pode fazer isso perfeitamente, por exemplo:

MyClass[][] x = new MyClass[10][];

for(int i = 0; i < 10; i++)
{
    x[i] = new MyClass[(30 + i)];
}

Este pode ser um artigo interessante para você.

Frederik Gheysels
fonte
5

Anúncio 3) Para inicializar esse tipo de monstro [][,][,], você pode fazer algo como:

        int [,][,] multiArr1 = { { new int[,] { { 2, 2 }, { 1, 1 } },
                                     new int[,] { { 2, 2 }, { 1, 1 } } },
                                     { new int[,] { { 2, 2 }, { 1, 1 } },
                                         new int[,] { { 2, 2 }, { 1, 1 } } } };
        int [,][,] multiArr2 = { { new int[,] { { 2, 2 }, { 1, 1 } },
                                     new int[,] { { 2, 2 }, { 1, 1 } } },
                                     { new int[,] { { 2, 2 }, { 1, 1 } },
                                         new int[,] { { 2, 2 }, { 1, 1 } } } };

        int [][,][,] superMultiArray = { multiArr1, multiArr2 };
nan
fonte
1

Se você estiver procurando por uma matriz multidimensional com limites definidos, sempre use a [,]sintaxe de estilo. Isso garantirá que cada porção tenha o mesmo tamanho.

Quando você usa, o [][]que realmente está acontecendo é que você está criando um array de arrays. Isso significa que cada array pode ter um tamanho diferente. Por exemplo:

int[][] jaggedArray = new int[5][]
for(int index = 0; index < jaggedArray.Length ; ++index)
{
    jaggedArray[index] = new int[index + 1];
}
Joshua Rodgers
fonte
1

A declaração inline seria semelhante a esta:

int[,] numbers = { {1, 2}, {3, 4}, {5, 6} };
Josiah Ruddell
fonte
1

Para o nº 1, veja esta pergunta SO

Para matrizes inline denteadas ou multidimensionais, consulte este guia de programação :

// Three-dimensional array.
int[, ,] array3D = new int[,,] { { { 1, 2, 3 }, { 4, 5, 6 } },
{ { 7, 8, 9 }, { 10, 11, 12 } } };

// Same array with dimensions specified at declaration.
int[, ,] array3Da = new int[2, 2, 3] { { { 1, 2, 3 }, { 4, 5, 6 } },
{ { 7, 8, 9 }, { 10, 11, 12 } } };

Você não precisa especificar as dimensões (array3D), mas se você sabe que eles nunca vão mudar, é útil saber quais dimensões você está usando (array3Da).

raiva
fonte
0

Você precisaria entender o funcionamento interno do array - o array multidimensional age como um array de dimensão única, exceto que a indexação dupla é convertida em um único.

Seu array Jagged em c # é um array de objetos que são arrays em turnos.

dvhh
fonte
0

Acho que a alocação de memória de matrizes 2d denteadas em C # é como matrizes 2d em C ++ e C. Porque as matrizes 2d denteadas têm um ponteiro que aponta para uma matriz de ponteiros e cada um desses ponteiros aponta para uma matriz de elementos (por exemplo, elementos inteiros); como este código em C ++,

int** 2DArr {new int* [number1]};
for (int i = 0; i < number1; i++)
{
   2DArr[i] = new int[number2];
}

a alocação de memória do código abaixo é a mesma dos arrays denteados 2d em C #. Mas estou em dúvida, você poderia explicar mais se eu pensar da maneira errada.

ARSD
fonte
0

Este post é antigo, mas aqui estão meus pensamentos sobre isso.

Matrizes denteadas são matrizes multidimensionais. Matrizes multidimensionais vêm em duas variedades: retangulares e irregulares. As matrizes retangulares representam um bloco de memória n-dimensional e as matrizes denteadas são matrizes de matrizes.

Matrizes retangulares

Matrizes retangulares são declaradas usando vírgulas para separar cada dimensão. A seguinte declaração declara uma matriz retangular bidimensional, em que as dimensões são 3 × 3:

int[,] matrix = new int [3, 3]; 

Matrizes denteadas

Matrizes denteadas são declaradas usando colchetes sucessivos para representar cada dimensão. Aqui está um exemplo de declaração de uma matriz bidimensional irregular, em que a dimensão externa é 3:

int[][] matrix = new int[3][];
Imir Hoxha
fonte
0

Para uma matriz multidimensional, pense em uma caixa ou retângulo. Cada linha tem o mesmo comprimento e cada coluna tem o mesmo comprimento.

Em uma matriz denteada, as linhas e colunas podem não ter o mesmo tamanho. Por exemplo, as colunas ou linhas podem ter tamanhos diferentes. Isso levaria a uma forma que pode não ser uma linha reta descendo os lados, como um retângulo. Em vez disso, os lados podem ser irregulares .

Agora eu usei 2 dimensões / 2 matrizes para este exemplo, mas isso se aplica a mais.

Roblem
fonte