Reputation: 40444
I have a way of doing Arrays in other languagues like this:
$x = "David"
$arr = @()
$arr[$x]["TSHIRTS"]["SIZE"] = "M"
This generates an error.
Upvotes: 45
Views: 319603
Reputation: 23623
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-Object {$_.Name -eq 'David' -and $_.Article -eq 'TShirt'} | Select Size
Or in newer PowerShell (Core) versions:
$arr | Where-Object 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
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:
(At design time you might use $Csv | Format-Csv
or $arr | Format-Csv
for this.)
$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
'
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.
Upvotes: 17
Reputation: 401
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")
Upvotes: 17
Reputation: 332
Two-dimensional arrays can be defined this way too as jagged array:
$array = New-Object system.Array[][] 5,5
This has the nice feature that
$array[0]
outputs a one-dimensional array, containing $array[0][0]
to $array[0][4]
.
Depending on your situation you might prefer it over $array = New-Object 'object[,]' 5,5
.
(I would have commented to CB above, but stackoverflow does not let me yet)
Upvotes: 2
Reputation: 156
Im found pretty cool solvation for making arrays in array.
$GroupArray = @()
foreach ( $Array in $ArrayList ){
$GroupArray += @($Array , $null)
}
$GroupArray = $GroupArray | Where-Object {$_ -ne $null}
Upvotes: 1
Reputation: 11
Lent from above:
$arr = ConvertFrom-Csv @'
Name,Article,Size
David,TShirt,M
Eduard,Trouwsers,S
'@
Print the $arr:
$arr
Name Article Size
---- ------- ----
David TShirt M
Eduard Trouwsers S
Now select 'David'
$arr.Where({$_.Name -eq "david"})
Name Article Size
---- ------- ----
David TShirt M
Now if you want to know the Size of 'David'
$arr.Where({$_.Name -eq "david"}).size
M
Upvotes: 1
Reputation: 101
Another thread pointed here about how to add to a multidimensional array in Powershell. I don't know if there is some reason not to use this method, but it worked for my purposes.
$array = @()
$array += ,@( "1", "test1","a" )
$array += ,@( "2", "test2", "b" )
$array += ,@( "3", "test3", "c" )
Upvotes: 5
Reputation: 3193
Using the .net syntax (like CB pointed above)
you also add coherence to your 'tabular' array...
if you define a array...
and you try to store diferent types
Powershell will 'alert' you:
$a = New-Object 'byte[,]' 4,4
$a[0,0] = 111; // OK
$a[0,1] = 1111; // Error
Of course Powershell will 'help' you
in the obvious conversions:
$a = New-Object 'string[,]' 2,2
$a[0,0] = "1111"; // OK
$a[0,1] = 111; // OK also
Upvotes: 1
Reputation: 9437
Here is a simple multidimensional array of strings.
$psarray = @(
('Line' ,'One' ),
('Line' ,'Two')
)
foreach($item in $psarray)
{
$item[0]
$item[1]
}
Output:
Line
One
Line
Two
Upvotes: 8
Reputation: 4278
you could also uses System.Collections.ArrayList
to make a and array of arrays or whatever you want.
Here is an example:
$resultsArray= New-Object System.Collections.ArrayList
[void] $resultsArray.Add(@(@('$hello'),2,0,0,0,0,0,0,1,1))
[void] $resultsArray.Add(@(@('$test', '$testagain'),3,0,0,1,0,0,0,1,2))
[void] $resultsArray.Add("ERROR")
[void] $resultsArray.Add(@(@('$var', '$result'),5,1,1,0,1,1,0,2,3))
[void] $resultsArray.Add(@(@('$num', '$number'),3,0,0,0,0,0,1,1,2))
One problem, if you would call it a problem, you cannot set a limit. Also, you need to use [void]
or the script will get mad.
Upvotes: 1
Reputation: 301037
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
Upvotes: 67
Reputation: 60910
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
Upvotes: 35