ทำไมเราถึงมีทั้งอาร์เรย์แบบหยักและอาร์เรย์หลายมิติ


89
  1. อะไรคือความแตกต่างระหว่างอาร์เรย์แบบหยักและอาร์เรย์หลายมิติ มีประโยชน์ต่อกันหรือไม่?

  2. แล้วทำไม Visual Studio ถึงไม่อนุญาตให้ฉันทำไฟล์

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

    (เราเคยทำใน C ++ แต่ใน C # มันขีดเส้นใต้ [20] ด้วยเส้นสีแดงดิ้น .. บอกว่าตัวระบุอันดับไม่ถูกต้อง)

    แต่มีความสุขกับ

    MyClass[,] abc = new MyClass[10,20];
    
  3. ในที่สุดฉันจะเริ่มต้นสิ่งนี้ในบรรทัดเดียวได้อย่างไร (เช่นเดียวกับที่เราทำในอาร์เรย์ธรรมดา{new xxx...}{new xxx....})

    MyClass[][,][,] itemscollection;
    

11
จุดรวมของอาร์เรย์ที่ขรุขระคืออาร์เรย์ที่ "ซ้อนกัน" ไม่จำเป็นต้องมีขนาดสม่ำเสมอ
Ani

1
msdn.microsoft.com/en-us/library/2yd9wwz4(v=vs.71).aspx - ไวยากรณ์อาร์เรย์หลายมิติเป็น [X, Y] ถูกต้องตามเอกสาร
ndtreviv

คำถามย่อยเพิ่มเติม: สามารถใช้ foreach () กับอาร์เรย์หลายมิติได้หรือไม่?
Serge Wautier

@Serge - ของหลักสูตรเช่นการดำเนินการArray IEnumerableคุณสามารถลองและดูด้วยตัวคุณเองได้เสมอ :)
thecoop

คำตอบ:


107
  1. อาร์เรย์ขรุขระคืออาร์เรย์ของอาร์เรย์ดังนั้นอาร์เรย์int[][]คืออาร์เรย์int[]ซึ่งแต่ละอันอาจมีความยาวต่างกันและครอบครองบล็อกของตนเองในหน่วยความจำ อาร์เรย์หลายมิติ ( int[,]) เป็นหน่วยความจำบล็อกเดียว (โดยพื้นฐานแล้วเมทริกซ์)

  2. คุณไม่สามารถสร้างได้MyClass[10][20]เนื่องจากแต่ละอาร์เรย์ย่อยต้องเริ่มต้นแยกกันเนื่องจากเป็นวัตถุที่แยกจากกัน:

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

    A MyClass[10,20]ก็โอเคเพราะกำลังเริ่มต้นออบเจ็กต์เดียวเป็นเมทริกซ์ที่มี 10 แถวและ 20 คอลัมน์

  3. A MyClass[][,][,]สามารถเริ่มต้นได้เช่นนั้น (ไม่ได้ทดสอบการคอมไพล์):

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

โปรดทราบว่า CLR ได้รับการปรับให้เหมาะสมอย่างมากสำหรับการเข้าถึงอาร์เรย์แบบมิติเดียวดังนั้นการใช้อาร์เรย์แบบหยักจะเร็วกว่าอาร์เรย์หลายมิติที่มีขนาดเท่ากัน


6
คุณช่วยชี้ให้เราเห็นหลักฐานบางอย่างที่ว่าการเข้าถึงอาร์เรย์มิติเดียวเร็วกว่าได้ไหม
GreyCloud


มีกรณีการใช้งาน (ทั่วไป) สำหรับอาร์เรย์หลายมิติหรือไม่?
ryanwebjackson

1
ตัวอย่าง: กระดานหมากรุกvar board = new Piece[8, 8];เป็นเมทริกซ์การเปลี่ยนแปลง var m = new double[2, 2];
Olivier Jacot-Descombes

40

อาร์เรย์ขรุขระคืออาร์เรย์ของอาร์เรย์ แต่ละอาร์เรย์ไม่รับประกันว่าจะมีขนาดเท่ากัน คุณสามารถมี

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

มันคือชุดของอาร์เรย์ที่เกี่ยวข้อง

ในทางกลับกันอาร์เรย์หลายมิติเป็นการจัดกลุ่มที่เหนียวแน่นเช่นกล่องตารางคิวบ์ ฯลฯ ซึ่งไม่มีความยาวผิดปกติ กล่าวคือ

int i = array[1,10];
int j = array[2,10]; // 10 will be available at 2 if available at 1

ฉันลองใช้รหัสของคุณแล้ว มันไม่ได้รวบรวม ลองเพิ่ม int [3] แล้วลองjaggedArray[0] = int[3]{ 1, 2, 3 };
barlop

ฉันรู้ว่านี่เป็นเรื่องเก่า แต่เพียงเพื่อให้ข้อมูล int [3] นั้นไม่จำเป็น int [] ง่ายๆคือทุกสิ่งที่สำคัญ int [] [] myArray = int ใหม่ [5] []; myArray [0] = int ใหม่ [] {1, 2, 3, 4}; นี่คือสิ่งที่จำเป็น
Velocibadgery

เอาสิ่งนี้ไปรวบรวมใน C # ได้ไหม ฉันไม่สามารถรวบรวมได้jaggedArray[0] = { 1, 2, 3 };เว้นแต่ฉันจะเปลี่ยนเป็น= new[] { 1, 2, 3 }(หรือ= new int[] { 1, 2, 3 }ก่อน C # 3.0) ตามคู่มือการเขียนโปรแกรม C #ของ Microsoft "คุณสามารถประกาศตัวแปรอาร์เรย์ได้โดยไม่ต้องสร้าง แต่คุณต้องใช้ตัวดำเนินการใหม่เมื่อคุณกำหนดอาร์เรย์ใหม่ให้กับตัวแปรนี้"
Joel V. Earnest-DeYoung

11

อาร์เรย์สี่เหลี่ยมจะมีจำนวนคอลัมน์เท่ากันสำหรับทุกแถวเสมอ

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

ทุกแถวมี 30 คอลัมน์ในขณะที่ในอาร์เรย์หยักไม่จำเป็นต้องใช้ ดังนั้นฉันคิดว่าคุณจะต้องเริ่มต้นทุก 'แถว' ในอาร์เรย์หยักแยกกัน:

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

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

ในความเป็นจริงนั่นหมายความว่าไม่ใช่ทุกแถวในอาร์เรย์ที่ขรุขระจะต้องมีองค์ประกอบจำนวนเท่ากัน (ในตัวอย่างของฉันมีองค์ประกอบจำนวนเท่ากัน แต่ไม่จำเป็นต้องใช้)

คุณสามารถทำได้อย่างสมบูรณ์แบบเช่น:

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

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

นี่อาจเป็นบทความที่น่าสนใจสำหรับคุณ


5

โฆษณา 3) ในการเริ่มต้นสัตว์ประหลาดเช่น[][,][,]นี้คุณสามารถทำสิ่งต่อไปนี้:

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

1

หากคุณกำลังมองหาอาร์เรย์หลายมิติที่กำหนดขอบเขตให้ใช้[,]ไวยากรณ์สไตล์เสมอ เพื่อให้แน่ใจว่าแต่ละส่วนมีขนาดเท่ากัน

เมื่อคุณใช้[][]สิ่งที่เกิดขึ้นจริงคือคุณกำลังสร้างอาร์เรย์อาร์เรย์ ซึ่งหมายความว่าแต่ละอาร์เรย์สามารถมีขนาดแตกต่างกันได้ ตัวอย่างเช่น:

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


1

สำหรับ # 1 โปรดดูคำถาม SO นี้

สำหรับอาร์เรย์อินไลน์แบบหยักหรือหลายมิติโปรดดูคู่มือการเขียนโปรแกรมนี้:

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

คุณไม่จำเป็นต้องระบุขนาด (array3D) แต่ถ้าคุณรู้ว่าจะไม่มีการเปลี่ยนแปลงคุณควรทราบว่าคุณใช้มิติข้อมูลใด (array3Da)


0

คุณจะต้องเข้าใจการทำงานภายในของอาร์เรย์ว่าอาร์เรย์หลายมิติทำหน้าที่เป็นอาร์เรย์มิติเดียวยกเว้นว่าการสร้างดัชนีคู่จะถูกแปลงเป็นอาร์เรย์เดียว

อาร์เรย์ Jagged ของคุณใน c # คืออาร์เรย์ของวัตถุที่อยู่ในอาร์เรย์แบบผลัดกัน


0

ฉันคิดว่าการจัดสรรหน่วยความจำอาร์เรย์แบบหยัก 2d ใน C # นั้นเหมือนกับอาร์เรย์ 2d ใน C ++ และ C เนื่องจากอาร์เรย์แบบหยัก 2d มีตัวชี้ที่ชี้ไปยังอาร์เรย์ของพอยน์เตอร์ซึ่งแต่ละตัวชี้นี้ชี้ไปยังอาร์เรย์ขององค์ประกอบ (เช่นองค์ประกอบจำนวนเต็ม) เช่นรหัสนี้ใน C ++

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

การจัดสรรหน่วยความจำของรหัสร้องจะเหมือนกับอาร์เรย์ 2d หยักใน C # แต่ฉันสงสัยคุณช่วยอธิบายเพิ่มเติมได้ไหมถ้าฉันคิดผิด


0

โพสต์นี้เก่า แต่นี่คือความคิดของฉันเกี่ยวกับเรื่องนั้น

อาร์เรย์ที่มีรอยหยักคืออาร์เรย์หลายมิติ อาร์เรย์หลายมิติมีให้เลือก 2 แบบ ได้แก่ แบบสี่เหลี่ยมและแบบหยัก อาร์เรย์สี่เหลี่ยมเป็นตัวแทนของบล็อกหน่วยความจำ n มิติและอาร์เรย์แบบหยักคืออาร์เรย์ของอาร์เรย์

อาร์เรย์สี่เหลี่ยม

อาร์เรย์สี่เหลี่ยมถูกประกาศโดยใช้ลูกน้ำเพื่อแยกแต่ละมิติ คำสั่งต่อไปนี้ประกาศอาร์เรย์สองมิติรูปสี่เหลี่ยมผืนผ้าโดยมีขนาด 3 × 3:

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

อาร์เรย์ขรุขระ

อาร์เรย์ที่มีรอยหยักถูกประกาศโดยใช้วงเล็บเหลี่ยมต่อเนื่องกันเพื่อแสดงถึงแต่ละมิติ นี่คือตัวอย่างของการประกาศอาร์เรย์สองมิติที่ขรุขระโดยที่มิตินอกสุดคือ 3:

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

0

สำหรับอาร์เรย์หลายมิติให้นึกถึงกล่องหรือสี่เหลี่ยมผืนผ้า แต่ละแถวมีความยาวเท่ากันและแต่ละคอลัมน์มีความยาวเท่ากัน

ในอาร์เรย์ที่ขรุขระแถวและคอลัมน์อาจมีขนาดไม่เท่ากัน ตัวอย่างเช่นคอลัมน์หรือแถวอาจมีขนาดแตกต่างกัน สิ่งนี้จะนำไปสู่รูปทรงที่อาจไม่ใช่เส้นตรงด้านข้างเหมือนสี่เหลี่ยมผืนผ้า แต่ด้านข้างอาจจะขรุขระ

ตอนนี้ฉันใช้ 2 มิติ / 2 อาร์เรย์สำหรับตัวอย่างนี้ แต่ใช้กับมากกว่านี้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.