Home > Net >  PowerShell, Can an array list be multi-dimensional?
PowerShell, Can an array list be multi-dimensional?

Time:12-17

I have a script that builds an array list using a text file like so:

$Hosts=[System.Collections.ArrayList]@(ForEach ($l in (get-content .\Config.conf | Where-Object {$_ -match "Host..="} | Where-Object {$_ -notmatch "#"})) {($l.split('=')[1]).split(",")[0]})

Now I have a need to change this into a multidimensional array, but nothing I try works; so at this point I am curious, can array lists be multidimensional?

I have tried a few different syntax such as:

$Hosts=[System.Collections.ArrayList]@((),())
$Hosts=[System.Collections.ArrayList]@(@(),@())
$Hosts=[System.Collections.ArrayList]@(,(),())

I have even tried building 2 array lists, then combining them as such:

$Hosts=[System.Collections.ArrayList]@(ForEach ($l in (get-content .\Config.conf | Where-Object {$_ -match "Host..="} | Where-Object {$_ -notmatch "#"})) {($l.split('=')[1]).split(",")[0]})
$Location=[System.Collections.ArrayList]@(ForEach ($l in (get-content .\Config.conf | Where-Object {$_ -match "Host..="} | Where-Object {$_ -notmatch "#"})) {($l.split('=')[1]).split(",")[1]})

$NewArry[System.Collections.ArrayList]@(($Hosts),($Location))

Everything I have tried turns into a single dimension array.

I am using an array list so I can modify the array without rebuilding it...basically the first logic I use the array in, is a ping test, and I remove the unresponsive hosts....I now need to correlate the location to the host; and the way I thought I need to do it is to build the multidimensional array, so that when an unresponsive host is removed, the correlating location is also removed...that way the location list and host lists don't become mis-matched.

Please let me know your thoughts, including if there is a different way to go about this altogether. Keep in mind, I can't use the regular PowerShell array, because it takes to long to rebuild the array every time I need to make a change to it. Thank you!

CodePudding user response:

Instead of trying to parse the host and location details into two separate list, create a single list of objects with both pieces of information attached as properties:

$list = foreach($line in Get-Content .\Config.conf | Where-Object {$_ -match "Host..="} | Where-Object {$_ -notmatch "#"}){
    # parse the line, extract relevant details
    $value = $line.Split('=')[1]
    $hosthame,$location = $value.Split(',')

    # Create a new object 
    [pscustomobject]@{
      Hostname = $hostname
      Location = $location
    }
}

Now you can interrogate your data based on a single property value:

PS ~> $list |Where-Object Hostname -like "*myPC*"

Hostname  Location
--------  --------
myPC-01   Hogwarts

CodePudding user response:

Mathias' helpful answer is undoubtedly the best solution to your problem (though you may want to use [System.Collections.ArrayList] $list = foreach ... to make $list a resizable data structure that you can remove elements from).


To address you question as asked:

  • Unlike arrays, System.Collections.ArrayList instances can not be multi-dimensional.

  • However, you can nest them, to create the - resizable - analog to a jagged array, i.e. an array list of array lists.

Note: The above also applies to the related generic System.Collections.Generic.List[T] type, which may be preferable for type safety and for potentially better performance.

A simplified example:

# You can place any statement inside @(...) to initialize the nested lists.
# Use [System.Collections.ArrayList] @() or [System.Collections.ArrayList]::new()
# to start with empty lists.
$nestedArrayList = 
  [System.Collections.ArrayList] (
    [System.Collections.ArrayList] @('host1', 'host2'),
    [System.Collections.ArrayList] @('location1', 'location2')
  )

Now, $nestedArrayList[0][1] yields host2, for example, and $nestedArrayList[1].RemoveAt(0) removes location1 from the 2nd list.


As for what you tried:

  • () is a syntax error - only @() works to create an empty array.

  • [System.Collections.ArrayList] @(@(),@()) works syntactically, but makes the elements of the array list by-definition-fixed-size arrays.

That is, you won't be able to add or remove elements from these nested arrays (though you could assign new arrays - or an object of any other type, for that matter, given that ArrayList has object-typed elements).

  • Related