A multidimensional array in PowerShell is usually an array of arrays, called a jagged array. Each inner array is a row, and you read a value with two indexes, $array[row][column]:
$sales = @(
@('Austin', 18250, 21400),
@('Denver', 12400, 13900),
@('Miami', 20975, 19800)
)
"Rows: $($sales.Count)"
"Row 1, column 0: $($sales[1][0])"
"Miami Q2 sales: $($sales[2][2])"
Output:
Rows: 3
Row 1, column 0: Denver
Miami Q2 sales: 19800
PowerShell also has true two-dimensional arrays like [int[,]], covered further down. I ran every example in PowerShell 7.6 and Windows PowerShell 5.1, with the same results.
Use [row][column], not [row,column]
On a jagged array, a comma inside one pair of brackets means “these indexes”, so $sales[0,1] returns rows 0 and 1 instead of one value:
$sales = @(
@('Austin', 18250, 21400),
@('Denver', 12400, 13900),
@('Miami', 20975, 19800)
)
"`$sales[0][1] is one value: $($sales[0][1])"
"`$sales[0,1] is two rows: $(($sales[0,1] | ForEach-Object { $_[0] }) -join ', ')"
Output:
$sales[0][1] is one value: 18250
$sales[0,1] is two rows: Austin, Denver
![PowerShell jagged array $a[0][1] vs $a[0,1]](https://powershellfaqs.com/wp-content/uploads/2026/09/powershell-jagged-array-index-vs-comma.png)
The [row,column] form is only for true 2D arrays. Microsoft explains array indexing in about_Arrays.
Add a row to a multidimensional array
Adding an array with + or += unrolls it, so the new row’s values become separate items. Put the unary comma in front to add it as one row:
$sales = @(
@('Austin', 18250, 21400),
@('Denver', 12400, 13900),
@('Miami', 20975, 19800)
)
$wrong = $sales + @('Seattle', 15100, 16250)
"Adding @(...) gives $($wrong.Count) items, and item 3 is $($wrong[3])"
$sales += ,@('Seattle', 15100, 16250)
"Adding ,@(...) gives $($sales.Count) rows, and row 3 is $($sales[3] -join ' / ')"
Output:
Adding @(...) gives 6 items, and item 3 is Seattle
Adding ,@(...) gives 4 rows, and row 3 is Seattle / 15100 / 16250

The comma operator wraps the row in a one-item array, which += then unwraps once. Microsoft describes it as the comma operator in about_Operators.
A single row needs the comma too
For the same reason, @(@(…)) with only one row collapses into a flat array:
$one = @(@('Austin', 18250))
"Without a comma: $($one.Count) items, first is $($one[0])"
$one = ,@('Austin', 18250)
"With a comma: $($one.Count) row, first is $($one[0] -join ' / ')"
Output:
Without a comma: 2 items, first is Austin
With a comma: 1 row, first is Austin / 18250
If you build rows in a loop, add each one with ,@() or use the List shown at the end.
True two-dimensional arrays
For a fixed grid, like a seat map, create a real 2D array with a type and size. Index it with [row, column], and use GetLength for each dimension:
$seats = [string[,]]::new(3, 4)
for ($r = 0; $r -lt $seats.GetLength(0); $r++) {
for ($c = 0; $c -lt $seats.GetLength(1); $c++) { $seats[$r, $c] = '-' }
}
$seats[1, 2] = 'X'
$seats[0, 0] = 'X'
"Rank: $($seats.Rank), rows: $($seats.GetLength(0)), columns: $($seats.GetLength(1)), cells: $($seats.Count)"
for ($r = 0; $r -lt 3; $r++) {
"Row $($r + 1): " + ((0..3 | ForEach-Object { $seats[$r, $_] }) -join ' ')
}
Output:
Rank: 2, rows: 3, columns: 4, cells: 12
Row 1: X - - -
Row 2: - - X -
Row 3: - - - -

Count is the total number of cells, 12 here, not the number of rows. Rank tells you how many dimensions the array has.
2D arrays have a fixed size
You can’t add rows to a [,] array, and an index outside it throws an error:
$matrix = [int[,]]::new(2, 2)
try { $matrix[2, 0] = 5 } catch { 'Row 2 does not exist, a 2x2 array has rows 0 and 1' }
"Total cells stay fixed at $($matrix.Count)"
Output:
Row 2 does not exist, a 2x2 array has rows 0 and 1
Total cells stay fixed at 4
Pick a jagged array when rows can differ in length or grow, and a [,] array for grids whose size you know up front.
Loop through a multidimensional array
foreach over a jagged array gives you one row at a time:
$sales = @(
@('Austin', 18250, 21400),
@('Denver', 12400, 13900),
@('Miami', 20975, 19800)
)
foreach ($row in $sales) {
$total = $row[1] + $row[2]
'{0,-7} Q1 {1,7:C0} Q2 {2,7:C0} Total {3,8:C0}' -f $row[0], $row[1], $row[2], $total
}
Output:
Austin Q1 $18,250 Q2 $21,400 Total $39,650
Denver Q1 $12,400 Q2 $13,900 Total $26,300
Miami Q1 $20,975 Q2 $19,800 Total $40,775
For a [,] array, use two for loops with GetLength(0) and GetLength(1), as in the seat map example.
A better option for tables: objects
If each row describes one thing, an array of objects is easier to read, sort and export than an array of arrays:
$sales = @(
@('Austin', 18250, 21400),
@('Denver', 12400, 13900),
@('Miami', 20975, 19800)
)
$sales | ForEach-Object {
[pscustomobject]@{ City = $_[0]; Q1 = $_[1]; Q2 = $_[2] }
} | Sort-Object -Property Q2 -Descending | Format-Table
Output:
City Q1 Q2
---- -- --
Austin 18250 21400
Miami 20975 19800
Denver 12400 13900
Named properties replace magic column numbers like $_[2]. Creating an array of objects covers this in detail.
A growable list of rows
For rows you’ll add and remove often, use a List of arrays. Add takes the row as one item, with no comma needed:
$rows = [System.Collections.Generic.List[object[]]]::new()
$rows.Add(@('WEB01', 'Online'))
$rows.Add(@('SQL01', 'Offline'))
"Rows: $($rows.Count), second server: $($rows[1][0]) is $($rows[1][1])"
Output:
Rows: 2, second server: SQL01 is Offline
Frequently Asked Questions
How do I create a multidimensional array in PowerShell?
Use an array of arrays: $grid = @(@(1, 2), @(3, 4)). For a fixed grid, use [int[,]]::new(3, 4).
How do I access an element in a multidimensional array?
Use $grid[row][column] for an array of arrays, and $grid[row, column] for a [,] array.
How do I add a row to a multidimensional array?
Use the unary comma: $grid += ,@('Seattle', 15100). Without it, the values are added as separate items.
How do I get the number of rows and columns?
For a [,] array, use $grid.GetLength(0) for rows and $grid.GetLength(1) for columns. For an array of arrays, use $grid.Count and $grid[0].Count.
Why does my one-row array have the wrong count?
@(@(‘a’, ‘b’)) flattens into two items. Write ,@('a', 'b') to keep it as one row.
More array techniques you can combine with these:
Bijay Kumar is an esteemed author and the mind behind PowerShellFAQs.com, where he shares his extensive knowledge and expertise in PowerShell, with a particular focus on SharePoint projects. Recognized for his contributions to the tech community, Bijay has been honored with the prestigious Microsoft MVP award. With over 15 years of experience in the software industry, he has a rich professional background, having worked with industry giants such as HP and TCS. His insights and guidance have made him a respected figure in the world of software development and administration. Read more.