echoShib
echoShib

Reputation: 11

Iterate through multiple arrays in powershell script

I am attempting to use multiple arrays to pass multiple server names, and maybe other elements, that maybe be needed in conjunction to each other to a function's set of Parameters in a Powershell function. While using a single loop, if that is even possible.

I wanted to script this process so you could pass an array via a parameter as a larger function to the 2nd function but use arrays. Instead of nested Hashtable.

This is similar to what i was attempting to do but I cant seem to get the arrays to pass each element one at a time for each respective array.

This is what I have gotten to get a "similar" result but I will not work if I have to have the index position via the [0].

$servers1 = @('serv1-01','serv1-02')
$servers2 = @('serv2-01','serv2-02')

$collectionItems = @()
    $temp = New-Object System.Object
    $temp | Add-Member -MemberType NoteProperty -Name "Server1" -Value $servers1
    $temp | Add-Member -MemberType NoteProperty -Name "Server2" -Value $servers2
    $collectionItems += $temp
Write-Host "Server1 is $($item.Server1[0]) and Server2 is $($item.Server2[0])"

foreach ($item in $collectionItems)
{
    Write-Host "Server1 is $($item.Server1) and Server2 is $($item.Server2)"
}


#### This is the output if you run the above script#####
Server1 is serv1-01 and Server2 is serv2-01
Server1 is serv1-01 serv1-02 and Server2 is serv2-01 serv2-02

Below is kind of the skeleton of what i am trying to accomplish... I know that you can have a nested Hashtable that uses one of the Key:Value pairs as an array, but im not sure if you can pass that in at the commandline as a nested Hashtable or how that would work to use the params to add to the nested sections of the Hashtable vs keeping this hashtable up to date ((Which would not be ideal))

I know the code below will not work but its the best visual representation of my desired end goal

function Bigger-ServerListAdding { 
#List of servers to add some config too
$servers1 = @('serv1-01','serv1-02')
$servers2 = @('serv2-01','serv2-02')

#This variable can be passed in and fixed with a -join ',' as a comma separated list
$componentlist = @('sister','brother','uncle','mom','dad')


###This section should do each element not the entire array list being passed###
foreach (item in $somecollection){
 Set-TheseServersOnaConfig -Server1 $item.servers1 -Server2 $item.servers2 -ComponentList $($componentlist -join ",")
}


}

Mind you this is like he 2nd question i've ever asked on StackOverflow. Any suggestions as this type of thing in the future.

Thank you very much!

Upvotes: 1

Views: 3747

Answers (1)

Matthew
Matthew

Reputation: 1166

Powershell's handling of multi-dimensional arrays is pretty lousy, and I try to avoid using them any chance I get. Jawad's answer in the comments, to create an array of HashTables, is one way of avoiding using them, but it doesn't take advantage of PowerShell's object oriented nature. As an example, I want to pass information about 3 computers, their names, HD Size, and Memory Size. Using the HashTable solution, you get:

$Array = @()
$Array += @{Computer='star';HD='2TB';Memory='16GB'}
$Array += @{Computer='comet';HD='1TB';Memory='8GB'}
$Array += @{Computer='meteor';HD='3TB';Memory='16GB'}

This array contains 3 items:

PS> $Array.Count
3

And you can access the data as you would expect:

PS> $Array[1]['Computer']
comet

But you can also access it as a property.

PS> $Array[1].Computer
comet

But, when you list the contents, the data is intermingled, and not easy to understand:

PS> $Array
Name                           Value                                                                                                  
----                           -----                                                                                                  
Memory                         16GB                                                                                                   
HD                             2TB                                                                                                    
Computer                       star                                                                                                   
Memory                         8GB                                                                                                    
HD                             1TB                                                                                                    
Computer                       comet                                                                                                  
Memory                         16GB                                                                                                   
HD                             3TB                                                                                                    
Computer                       meteor        

And further, the "fields" you have created are not properties of the object, but are members of the keys array, and are more difficult to iterate through than they need to be.

PS C:\Users\Matthew> $Array[0] | gm

   TypeName: System.Collections.Hashtable

Name              MemberType            Definition                                                                                    
----              ----------            ----------                                                                                    
Add               Method                void Add(System.Object key, System.Object value), void IDictionary.Add(System.Object key, S...
Clear             Method                void Clear(), void IDictionary.Clear()                                                        
Clone             Method                System.Object Clone(), System.Object ICloneable.Clone()                                       
Contains          Method                bool Contains(System.Object key), bool IDictionary.Contains(System.Object key)                
ContainsKey       Method                bool ContainsKey(System.Object key)                                                           
ContainsValue     Method                bool ContainsValue(System.Object value)                                                       
CopyTo            Method                void CopyTo(array array, int arrayIndex), void ICollection.CopyTo(array array, int index)     
Equals            Method                bool Equals(System.Object obj)                                                                
GetEnumerator     Method                System.Collections.IDictionaryEnumerator GetEnumerator(), System.Collections.IDictionaryEnu...
GetHashCode       Method                int GetHashCode()                                                                             
GetObjectData     Method                void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Seri...
GetType           Method                type GetType()                                                                                
OnDeserialization Method                void OnDeserialization(System.Object sender), void IDeserializationCallback.OnDeserializati...
Remove            Method                void Remove(System.Object key), void IDictionary.Remove(System.Object key)                    
ToString          Method                string ToString()                                                                             
Item              ParameterizedProperty System.Object Item(System.Object key) {get;set;}                                              
Count             Property              int Count {get;}                                                                              
IsFixedSize       Property              bool IsFixedSize {get;}                                                                       
IsReadOnly        Property              bool IsReadOnly {get;}                                                                        
IsSynchronized    Property              bool IsSynchronized {get;}                                                                    
Keys              Property              System.Collections.ICollection Keys {get;}                                                    
SyncRoot          Property              System.Object SyncRoot {get;}                                                                 
Values            Property              System.Collections.ICollection Values {get;}                                                  

However, if you were to take advantage of the Object nature of PowerShell, and instead of HashTables, use a PowerShell Custom Object (Type [PSCustomObject]), that changes dramatically. You can create a new object in many ways, but you can check out this TechNet Article PowerShell: Creating Custom Objects for a bunch of them. I'm going to use my personal favorite, which is extremely similar to the HashTable method, as it uses a HashTable to define the object parameters:

$Array = @()
$Array += [PSCustomObject]@{Computer='star';HD='2TB';Memory='16GB'}
$Array += [PSCustomObject]@{Computer='comet';HD='1TB';Memory='8GB'}
$Array += [PSCustomObject]@{Computer='meteor';HD='3TB';Memory='16GB'}

This gives you the same 3 items in the array:

PS> $Array.Count
3

Since the data is not in HashTable format, you can't access it like a HashTable, but you can access it like a property:

PS> $Array[1]['Computer']

PS> $Array[1].Computer
comet

But what you gain is that the data is kept separately in distinct objects:

PS> $Array

Computer HD  Memory
-------- --  ------
star     2TB 16GB  
comet    1TB 8GB   
meteor   3TB 16GB  

And the definition of the object is nice and neat:

PS> $Array[0] | gm

   TypeName: System.Management.Automation.PSCustomObject

Name        MemberType   Definition                    
----        ----------   ----------                    
Equals      Method       bool Equals(System.Object obj)
GetHashCode Method       int GetHashCode()             
GetType     Method       type GetType()                
ToString    Method       string ToString()             
Computer    NoteProperty string Computer=star          
HD          NoteProperty string HD=2TB                 
Memory      NoteProperty string Memory=16GB            

I hope this assists you in understanding more about how PowerShell handles data, and helps you make the right choices for how to store yours.

Upvotes: 1

Related Questions