'How to simplify multidimension array using Powershell?
I would like to create multidimension array in powershell, I tried this way and it works, but I want to simplified it to make it there is no repetition of name and pn. Anyone can give idea please, Thanks a lot
$array = @(
[PSCustomObject]@{name = 'PRODCT_1'; pn = 'gra-001'}
[PSCustomObject]@{name = 'PRODCT_11a'; pn = 'ght-001'}
[PSCustomObject]@{name = 'PRODCT_ca1'; pn = 'hasha-001'}
[PSCustomObject]@{name = 'PRODCT_ga1'; pn = '45-001'}
[PSCustomObject]@{name = 'PRODCT_4a1'; pn = 'aert-001'}
[PSCustomObject]@{name = 'PRODCT_ata41'; pn = '43-001'}
)
Solution 1:[1]
This creates an actual multidimensional array as the basis for generating the array of [pscustomobject]:
# Create multidimensional array
$temp = ('PRODCT_1', 'gra-001'),
('PRODCT_11a', 'ght-001'),
('PRODCT_ca1', 'hasha-001'),
('PRODCT_ga1', '45-001'),
('PRODCT_4a1', 'aert-001'),
('PRODCT_ata41', '43-001')
# Create single-dimensional array of pscustomobject
$array = $temp | Select-Object @{ n='name'; e={ $_[0] }},
@{ n='pn'; e={ $_[1] }}
# Output to console
$array
If you prefer, you could also do it using a single statement, without a temporary variable:
$array = (
('PRODCT_1', 'gra-001'),
('PRODCT_11a', 'ght-001'),
('PRODCT_ca1', 'hasha-001'),
('PRODCT_4a1', 'aert-001'),
('PRODCT_ata41', '43-001')
) | Select-Object @{ n='name'; e={ $_[0] }}, @{ n='pn'; e={ $_[1] }}
An even more succinct alternative using the intrinsic .ForEach method to directly create [PSCustomObject] array elements:
$array = (
('PRODCT_1', 'gra-001'),
('PRODCT_11a', 'ght-001'),
('PRODCT_ca1', 'hasha-001'),
('PRODCT_4a1', 'aert-001'),
('PRODCT_ata41', '43-001')
).ForEach{ [PSCustomObject]@{ name = $_[0]; pn = $_[1] } }
The latter is also the most efficient way, as it doesn't involve pipeline parameter-binding overhead.
Each of these produce the same output:
name pn
---- --
PRODCT_1 gra-001
PRODCT_11a ght-001
PRODCT_ca1 hasha-001
PRODCT_ga1 45-001
PRODCT_4a1 aert-001
PRODCT_ata41 43-001
Explanation for the Select-Object solutions:
For each "row" of $temp, the Select-Object command uses calculated properties to turn the array elements into object properties.
E. g. it takes the row ('PRODCT_1', 'gra-001'), which is an array of two elements. Then @{ n='name'; e={ $_[0] }} gets processed, which assigns the element at index 0 ('PRODCT_1') to property name. Then @{ n='pn'; e={ $_[1] }} gets processed, which assigns the element at index 1 ('gra-001') to property pn.
This process gets repeated for all remaining rows and we get an array of objects stored in $array, just like your original code does.
Solution 2:[2]
Not really simplified but this is one way you could do it using an ordered dictionary and loop through the key / value pairs to create new instances of PSCustomObject:
$dict = [ordered]@{
'PRODCT_1' = 'gra-001'
'PRODCT_11a' = 'ght-001'
'PRODCT_ca1' = 'hasha-001'
'PRODCT_ga1' = '45-001'
'PRODCT_4a1' = 'aert-001'
'PRODCT_ata41' = '43-001'
}
And then you can create the instances using either .GetEnumerator():
$dict.GetEnumerator() | ForEach-Object {
[pscustomobject]@{
Name = $_.Key
Pn = $_.Value
}
}
Or looping through the Keys:
$dict.PSBase.Keys | ForEach-Object {
[pscustomobject]@{
Name = $_
Pn = $dict[$_]
}
}
Lastly, as zett42 suggests you can combine .GetEnumerator() with Select-Object using a calculated property:
$dict.GetEnumerator() | Select-Object Name, @{N='Pn';E={$_.Value}}
Solution 3:[3]
Note
My answer keep the array of PSObject from your initial question but remove the name / pn repeat. I think in most cases, keeping the PSObject array structure is better (more flexible).
If you want an actual multidimensional array, Zett42's answer is what you want.
You could use a function or scriptblock invoke. the values will be assigned positionally so you don't have to write the names (name, pn) each times.
Using a function
Function Add-product($Name, $pn) { [PSCustomObject]@{name = $Name; pn = $pn } }
$array = @(
Add-product 'PRODCT_1' 'gra-001'
Add-product 'PRODCT_11a' 'ght-001'
Add-product 'PRODCT_ca1' 'hasha-001'
)
Using a scriptblock invoke
$add = {Param($Name,$pn) [PSCustomObject]@{name = $Name; pn = $pn}}
$array = @(
& $add 'PRODCT_1' 'gra-001'
& $add 'PRODCT_11a' 'ght-001'
& $add 'PRODCT_ca1' 'hasha-001'
)
Using CSV formatted data
This one is just another way to do it, although I'd probably never use it in any scenario, since I prefer the flexibility of using a custom function / scriptblock. That being said, it is definitely the most compact.
$array = @'
Name,Pn
PRODCT_1,gra-001
PRODCT_11a,ght-001
PRODCT_ca1,hasha-001
'@ | ConvertFrom-Csv
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | |
| Solution 3 |
