Dlaczego mamy zarówno tablicę postrzępioną, jak i tablicę wielowymiarową?

90
  1. Jaka jest różnica między tablicą postrzępioną a tablicą wielowymiarową. Czy jest jedna korzyść dla drugiej?

  2. I dlaczego Visual Studio nie pozwala mi na wykonanie pliku

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

    (Robiliśmy to w C ++, ale w C # podkreśla to [20] czerwoną, wijącą się linią .. Mówi nieprawidłowy specyfikator rangi)

    ale jest zadowolony z

    MyClass[,] abc = new MyClass[10,20];
    
  3. Wreszcie, jak mogę zainicjować to w jednej linii (tak jak robimy w prostej tablicy z {new xxx...}{new xxx....})

    MyClass[][,][,] itemscollection;
    
Shekhar_Pro
źródło
11
Cały sens tablicy postrzępionej polega na tym, że tablice „zagnieżdżone” nie muszą mieć jednakowego rozmiaru.
Ani,
1
msdn.microsoft.com/en-us/library/2yd9wwz4(v=vs.71).aspx - Składnia tablicy wielowymiarowej jako [X, Y] jest prawidłowa zgodnie z dokumentacją
ndtreviv
Dodatkowe pytanie podrzędne: Czy możliwe jest użycie metody foreach () z tablicą wielowymiarową?
Serge Wautier
@Serge - oczywiście jako Arraynarzędzia IEnumerable. Zawsze możesz spróbować i przekonać się sam :)
thecoop

Odpowiedzi:

107
  1. Tablica postrzępiona to tablica tablic, więc int[][]tablica jest tablicą int[], z których każda może mieć różną długość i zajmować własny blok w pamięci. Tablica wielowymiarowa ( int[,]) to pojedynczy blok pamięci (zasadniczo macierz).

  2. Nie możesz utworzyć, MyClass[10][20]ponieważ każda podtablica musi zostać zainicjowana osobno, ponieważ są to oddzielne obiekty:

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

    A MyClass[10,20]jest w porządku, ponieważ inicjalizuje pojedynczy obiekt jako macierz z 10 wierszami i 20 kolumnami.

  3. A MyClass[][,][,]można zainicjalizować w ten sposób (chociaż nie testowano kompilacji):

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

Należy pamiętać, że CLR jest mocno zoptymalizowany pod kątem dostępu do macierzy jednowymiarowej, więc użycie tablicy postrzępionej prawdopodobnie będzie szybsze niż tablica wielowymiarowa o tym samym rozmiarze.

thecoop
źródło
6
czy możesz wskazać nam jakieś dowody na to, że dostęp do jednowymiarowej tablicy jest szybszy?
GreyCloud,
Czy istnieje (powszechny) przypadek użycia tablicy wielowymiarowej?
ryanwebjackson
1
Przykłady: szachownica var board = new Piece[8, 8];, macierz transformacji var m = new double[2, 2]; .
Olivier Jacot-Descombes
40

Tablica postrzępiona to tablica tablic. Nie ma gwarancji, że każda tablica będzie tego samego rozmiaru. Mogłeś

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

To zestaw powiązanych tablic.

Z drugiej strony tablica wielowymiarowa jest bardziej spójnym zgrupowaniem, takim jak pudełko, stół, sześcian itp., Gdzie nie ma nieregularnych długości. To jest do powiedzenia

int i = array[1,10];
int j = array[2,10]; // 10 will be available at 2 if available at 1
Anthony Pegram
źródło
Wypróbowałem twój kod. To się nie skompilowało. Spróbuj dodać int [3], więc Spróbuj jaggedArray[0] = int[3]{ 1, 2, 3 };
barlop
Wiem, że to jest stare, ale tylko do celów informacyjnych int [3] nie jest konieczne. liczy się tylko zwykłe int []. int [] [] myArray = new int [5] []; myArray [0] = new int [] {1, 2, 3, 4}; To wszystko, co jest konieczne.
Velocibadgery
Czy możesz to skompilować w C #? Nie mogę skompilować, jaggedArray[0] = { 1, 2, 3 };chyba że zmienię go na = new[] { 1, 2, 3 }(lub = new int[] { 1, 2, 3 }przed C # 3.0). Zgodnie z podręcznikiem programowania języka C # firmy Microsoft : „Możesz zadeklarować zmienną tablicową bez jej tworzenia, ale musisz użyć nowego operatora podczas przypisywania nowej tablicy do tej zmiennej”.
Joel V. Earnest-DeYoung
11

Tablica prostokątna ma zawsze taką samą liczbę kolumn w każdym wierszu.

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

Każdy wiersz ma 30 kolumn, podczas gdy w tablicy postrzępionej nie jest to wymagane. Dlatego myślę, że będziesz musiał osobno zainicjować każdy „wiersz” w tablicy postrzępionej:

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

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

W rzeczywistości oznacza to, że nie każdy wiersz w tablicy postrzępionej musi zawierać taką samą liczbę elementów. (W moim przykładzie ma taką samą liczbę elementów, ale nie jest to wymagane).

Możesz to doskonale zrobić, na przykład:

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

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

To może być dla Ciebie interesujący artykuł.

Frederik Gheysels
źródło
5

Ad 3) Aby zainicjować takiego potwora jak [][,][,], możesz zrobić coś takiego:

        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
źródło
1

Jeśli szukasz wielowymiarowej tablicy z określonymi granicami, zawsze używaj [,]składni stylu. Dzięki temu każda porcja będzie miała jednakowy rozmiar.

Kiedy używasz [][]tego, co naprawdę się dzieje, tworzysz tablicę tablic. Oznacza to, że każda tablica może mieć inny rozmiar. Na przykład:

int[][] jaggedArray = new int[5][]
for(int index = 0; index < jaggedArray.Length ; ++index)
{
    jaggedArray[index] = new int[index + 1];
}
Joshua Rodgers
źródło
1

Deklaracja inline wyglądałaby mniej więcej tak:

int[,] numbers = { {1, 2}, {3, 4}, {5, 6} };
Josiah Ruddell
źródło
1

# 1, zobacz to pytanie SO

W przypadku nieregularnych lub wielowymiarowych tablic wbudowanych zobacz ten przewodnik programowania :

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

Nie musisz określać wymiarów (tablica3D), ale jeśli wiesz, że nigdy się nie zmienią, warto wiedzieć, jakich wymiarów używasz (tablica3Da).

rownage
źródło
0

Musisz zrozumieć wewnętrzne działanie tablicy, ponieważ tablica wielowymiarowa działa jak tablica jednowymiarowa, z wyjątkiem tego, że podwójne indeksowanie jest konwertowane na pojedynczą.

Twoja tablica postrzępiona w języku C # jest tablicą obiektów, które są po kolei tablicami.

dvhh
źródło
0

Myślę, że alokacja pamięci 2d tablic postrzępionych w C # jest jak tablice 2d w C ++ i C. Ponieważ tablice 2d postrzępione mają wskaźnik, który wskazuje na tablicę wskaźników, które każdy z tych wskaźników wskazuje na tablicę elementów (na przykład elementy całkowite); jak ten kod w C ++,

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

alokacja pamięci poniższego kodu jest taka sama jak 2d tablice postrzępione w języku C #. Ale mam wątpliwości, czy mógłbyś wyjaśnić więcej, jeśli myślę w niewłaściwy sposób.

ARSD
źródło
0

Ten post jest stary, ale oto moje przemyślenia na ten temat.

Tablice postrzępione to tablice wielowymiarowe. Tablice wielowymiarowe występują w dwóch odmianach: prostokątne i postrzępione. Tablice prostokątne reprezentują n-wymiarowy blok pamięci, a tablice postrzępione to tablice tablic.

Tablice prostokątne

Tablice prostokątne są deklarowane za pomocą przecinków, aby oddzielić każdy wymiar. Poniższa instrukcja deklaruje prostokątną dwuwymiarową tablicę o wymiarach 3 × 3:

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

Tablice postrzępione

Tablice postrzępione są deklarowane przy użyciu kolejnych nawiasów kwadratowych reprezentujących każdy wymiar. Oto przykład deklarowania postrzępionej dwuwymiarowej tablicy, w której najbardziej zewnętrzny wymiar to 3:

int[][] matrix = new int[3][];
Imir Hoxha
źródło
0

W przypadku tablicy wielowymiarowej pomyśl o pudełku lub prostokącie. Każdy wiersz ma taką samą długość, a każda kolumna ma tę samą długość.

W tablicy postrzępionej wiersze i kolumny mogą nie mieć tego samego rozmiaru. Na przykład kolumny lub wiersze mogą mieć różne rozmiary. Doprowadziłoby to do kształtu, który może nie być prostą linią wzdłuż boków, jak prostokąt. Zamiast tego boki mogą być postrzępione .

Teraz użyłem 2 wymiarów / 2 tablic w tym przykładzie, ale dotyczy to więcej.

Roblem
źródło