1
votes

I have been reading about arrays in powershell and hash tables, I know the basic workings of an array and how to use foreach loop to get items within the array, my challange here is slightly different. I would like to pay what I call a multi dimension array to a script, and process the items contained within the array.

What is my setup.

 $x = (1,"Server1",3,1),(4,"Server2",6,2),(3,"Server3",4,3)
 $k = 'serverid','servername','locationid','appid'    # key names correspond to data positions in each array in $x
 $h = @{}
      
      
 For($i=0;$i -lt $x[0].length; $i++){
     $x |
         ForEach-Object{
             [array]$h.($k[$i]) += [string]$_[$i]
         }
               
               
 } 

What am i trying to achieve ?

I am trying to achieve the structure of a database table within powershell. So literally treating each array item as a row.

So for example

(1,"Server1",3,1),(4,"Server2",6,2),(3,"Server3",4,3)

could be thought of as a table like below

enter image description here

I then want to loop for each item in the array to get the values, similar to the below example

[0].serverid = 1, [0].servername = server1, [0].locationid = 3, [0].applicationID = 1

[1].serverid = 4, [1].servername = server2, [1].locationid = 6, [1].applicationID = 2

what have I done ?

$x = (1,"Server1",3,1),(4,"Server2",6,2),(3,"Server3",4,3)
 $k = 'serverid','servername','locationid','appid'    # key names correspond to data positions in each array in $x
 $h = @{}


 For($i=0;$i -lt $x[0].length; $i++){
     $x |
         ForEach-Object{
             [array]$h.($k[$i]) += [string]$_[$i]
         }


 } 

$x


for ($i = 0; $i -lt $x.Count; $i++)
{
    $myserverid = $x[$i][0]
    $myservername = $x[$i][1]
    $mylocationid = $x[$i][2]
    $myappid = $x[$i][3]

    write-host $myserverid
}
 

The Issues

If I set the following $x = (1,"Server1",3,1), then the loop is somewhat incorrect which is why I think the approach is wrong (more than one item works i.e $x = (1,"Server1",3,1),(4,"Server2",6,2),(3,"Server3",4,3)). The loop only works if you have more than one item within the array, hence why I want to re-examine the way the loop works.

Thanks in advance

1
@mklement0 Thanks for the answer below, when testing I noticed an issue with using the unary operator by adding a "," this works when used inside a variable, but doesn't work when passed to a file like the example. Create a file called test.ps1 param ([array[]]$servers) for ($i = 0; $i -lt $servers.Count; $i++) { $myserverid = $servers[$i][0] $myservername = $servers[$i][1] $mylocationid = $servers[$i][2] $myappid = $servers[$i][3] write-host " $myserverid and $myservername and $mylocationid and $myappid" } .\tester.ps1 -servers ,(1,'Server1',3,1)` failsuser5544
To pass a nested array as an argument, you must wrap it in (...) as a whole: .\tester.ps1 -servers (,(1,'Server1',3,1))mklement0

1 Answers

1
votes

Your approach relies on a nested (jagged) array: That is, you have an array of subarrays, each of which represents the tuple of values you want to assign to properties.

If there's only one subarray, you must create the nested array explicitly, using the unary form of , the array constructor operator:

# Construct a 1-element array that contains the 4-element subarray.
$x = , (1,"Server1",3,1)

With two or more, subarrays, you implicitly get a nested array:

# Construct a 3-element array, each element of which contains a 4-element subarray.
$x = (1,"Server1",3,1), (4,"Server2",6,2), (3,"Server3",4,3)

Note that in PSv5+ you could use a custom class to solve your problem:

class Custom {
  [int] $serverid; [string] $servername;[int] $locationid; [int] $appid
  Custom($propValueArray) {
    $this.serverid = $propValueArray[0]; $this.servername = $propValueArray[1]; $this.locationid = $propValueArray[2]; $this.appid = $propValueArray[3]
  }
}

# Use an array cast to construct [Custom] instances.
# Note the need for (...) around the array, because casts have high
# precedence in PowerShell.
[Custom[]] ((1,"Server1",3,1), (4,"Server2",6,2), (3,"Server3",4,3))

This would allow for processing such as:

# Construct all objects
$objects = [Custom[]] ((1,"Server1",3,1), (4,"Server2",6,2), (3,"Server3",4,3))

# Process each object.
foreach ($object in $objects) {
   ($myserverid = $object.serverid) # assign a property to a var; `()` also outputs
   # ...
}