Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Powershell Multidimensional Arrays

Tags:

powershell

I have a way of doing Arrays in other languagues like this:

$x = "David"
$arr = @()

$arr[$x]["TSHIRTS"]["SIZE"] = "M"

This generates an error.

like image 411
basickarl Avatar asked Feb 22 '12 14:02

basickarl


People also ask

How do I create a multi dimensional array in PowerShell?

Syntax of PowerShell Multidimensional Array So for example, if we need an array of numbers than we can define int32, in the same way, if we need an array with string then we can define with string. $array = @( @(“data2”), @(“data3”), @(“data4”) …….)

Is it possible to create multidimensional arrays in PowerShell?

Working with arrays is a fairly straightforward process, but what a lot of people don't realize is that PowerShell does not limit you to using basic, run-of-the-mill arrays. You can also create multi-dimensional arrays.

What is a multidimensional array PowerShell?

A multidimensional array has multiple dimensions, in which case, the number of elements in each row of a dimension is the same. An element of a jagged array may contain a multidimensional array, and vice versa. Multidimensional arrays are stored in row-major order.

Does PowerShell have arrays?

PowerShell ArraysArrays in PowerShell can contain one or more items. An item can be a string, an integer, an object, or even another array, and one array can contain any combination of these items. Each of these items has an index, which always starts (sometimes confusingly) at 0.


4 Answers

You are trying to create an associative array (hash). Try out the following sequence of commands

$arr=@{}
$arr["david"] = @{}
$arr["david"]["TSHIRTS"] = @{}    
$arr["david"]["TSHIRTS"]["SIZE"] ="M"
$arr.david.tshirts.size

Note the difference between hashes and arrays

$a = @{} # hash
$a = @() # array

Arrays can only have non-negative integers as indexes

like image 162
manojlds Avatar answered Oct 21 '22 00:10

manojlds


from powershell.com:

PowerShell supports two types of multi-dimensional arrays: jagged arrays and true multidimensional arrays.

Jagged arrays are normal PowerShell arrays that store arrays as elements. This is very cost-effective storage because dimensions can be of different size:

$array1 = 1,2,(1,2,3),3
$array1[0]
$array1[1]
$array1[2]
$array1[2][0]
$array1[2][1]

True multi-dimensional arrays always resemble a square matrix. To create such an array, you will need to access .NET. The next line creates a two-dimensional array with 10 and 20 elements resembling a 10x20 matrix:

$array2 = New-Object 'object[,]' 10,20
$array2[4,8] = 'Hello'
$array2[9,16] = 'Test'
$array2

for a 3-dimensioanl array 10*20*10

$array3 = New-Object 'object[,,]' 10,20,10
like image 30
CB. Avatar answered Oct 21 '22 02:10

CB.


To extend on what manojlds said above is that you can nest Hashtables. It may not be a true multi-dimensional array but give you some ideas about how to structure the data. An example:

$hash = @{}

$computers | %{
    $hash.Add(($_.Name),(@{
        "Status" = ($_.Status)
        "Date"   = ($_.Date)
    }))
}

What's cool about this is that you can reference things like:

($hash."Name1").Status

Also, it is far faster than arrays for finding stuff. I use this to compare data rather than use matching in Arrays.

$hash.ContainsKey("Name1")

Hope some of that helps!

-Adam

like image 17
alistek Avatar answered Oct 21 '22 01:10

alistek


Knowing that PowerShell pipes objects between cmdlets, it is more common in PowerShell to use an array of PSCustomObjects:

$arr = @(
    [PSCustomObject]@{Name = 'David';  Article = 'TShirt'; Size = 'M'}
    [PSCustomObject]@{Name = 'Eduard'; Article = 'Trouwsers'; Size = 'S'}
)

Or for older PowerShell Versions (PSv2):

$arr = @(
    New-Object PSObject -Property @{Name = 'David';  Article = 'TShirt'; Size = 'M'}
    New-Object PSObject -Property @{Name = 'Eduard'; Article = 'Trouwsers'; Size = 'S'}
)

And grep your selection like:

$arr | Where {$_.Name -eq 'David' -and $_.Article -eq 'TShirt'} | Select Size

Or in newer PowerShell (Core) versions:

$arr | Where Name -eq 'David' | Where Article -eq 'TShirt' | Select Size

Or (just get the size):

$arr.Where{$_.Name -eq 'David' -and $_.Article -eq 'TShirt'}.Size

Addendum 2020-07-13

Syntax and readability

As mentioned in the comments, using an array of custom objects is straighter and saves typing, if you like to exhaust this further you might even use the ConvertForm-Csv (or the Import-Csv) cmdlet for building the array:

$arr = ConvertFrom-Csv @'
Name,Article,Size
David,TShirt,M
Eduard,Trouwsers,S
'@

Or more readable:

$arr = ConvertFrom-Csv @'
Name,   Article,   Size
David,  TShirt,    M
Eduard, Trouwsers, S
'@

Note: values that contain spaces or special characters need to be double quoted

Or use an external cmdlet like ConvertFrom-SourceTable which reads fixed width table formats:

$arr = ConvertFrom-SourceTable '
Name   Article   Size
David  TShirt    M
Eduard Trouwsers S
'

Indexing

The disadvantage of using an array of custom objects is that it is slower than a hash table which uses a binary search algorithm.
Note that the advantage of using an array of custom objects is that can easily search for anything else e.g. everybody that wears a TShirt with size M:

$arr | Where Article -eq 'TShirt' | Where Size -eq 'M' | Select Name

To build an binary search index from the array of objects:

$h = @{}
$arr | ForEach-Object {
    If (!$h.ContainsKey($_.Name)) { $h[$_.Name] = @{} }
    If (!$h[$_.Name].ContainsKey($_.Article)) { $h[$_.Name][$_.Article] = @{} }
    $h[$_.Name][$_.Article] = $_ # Or: $h[$_.Name][$_.Article]['Size'] = $_.Size
}

$h.david.tshirt.size
M

Note: referencing a hash table key that doesn't exist in Set-StrictMode will cause an error:

Set-StrictMode -Version 2
$h.John.tshirt.size
PropertyNotFoundException: The property 'John' cannot be found on this object. Verify that the property exists.
like image 14
iRon Avatar answered Oct 21 '22 01:10

iRon