Question

I'm having an issue figuring out how to specifically address one of two possible hash tables. Let me be clear - these hash tables are not nested, however there are two loops, one per hash table. Those loops ARE nested.

Within the inner loop - the one that is iterating through the keys in WWPNTable, I want to access the current key of the hash table being iterated by the outer loop. Given the current approach (I'm reasonably new to this), I've always just used $_, however that approach is very scope-dependent (used within the inner loop, $_ always refers to WWPNTable, and I need it to refer to VSANTable in this case).

$VSANTable.Add("A", $FabAVSAN)
$VSANTable.Add("B", $FabBVSAN)

#Outer loop
$VSANTable.Keys | % {

    $WWPNTable = @{}

    #Some code to populate WWPNTable....

    #Inner loop - note also the .GetEnumerator vs .Keys
    $WWPNTable.GetEnumerator() | Sort-Object Name | % { 
        Add-Content $ConfigFile ("zone name " + $($_.key) + "_TO_NTAP vsan " + $thisVSAN)
        Add-Content $ConfigFile ("    member pwwn " + $($_.value))

        if ($_ -eq "A") { ##This is not working right now because $_ at this scope refers to WWPNTable, not VSANTable.
            foreach ($target in $FabATargets) {
                Add-Content $ConfigFile ("    member pwwn " + $target)
            }
        } else {
                foreach ($target in $FabBTargets) {
                Add-Content $ConfigFile ("    member pwwn " + $target)
            }
        }
    }
}

I realize I'm also using .Keys for the outer loop and .GetEnumerator on the inner - this is not based on anything logical, I would love guidance there as well. My main goal is to be able to address the current key/value pair in the hash table being addressed by the outer loop, using code contained within the inner loop.

Was it helpful?

Solution

Switch to using foreach loops:

#Outer loop
foreach ($VSAN_Key in $VSANTable.Keys)
 {

    #Inner loop 
    foreach ($WWPN_Key in ($WWPNTable.keys | Sort-Object) )
     { 
       #Inner loop code

     } #End inner loop 

 } #End Outer loop

then within the inner loop, the current VSANTable key will be $VSAN_Key, and the current WWPNTable key will be $WWPN_Key.

As far as using .keys or .getenumerator() and selecting the key names, you're safe using .keys as long as you're sure you won't ever have an entry that is named "keys". If it hits that, you'll get back the value of that table entry instead of the key collection. If it's possible you could get that as a key name, then stick with .getenumerator().

OTHER TIPS

First, use mjolinor's answer, it is a better method, and less likely to cause confusion and scope issues.

Having said that, if you still want to run nested loops within the pipeline, the easiest way that I know of to accomplish a nested loop that references the current iteration of the outer loop is to assign $_ to a named variable before initiating the inner loop. For example:

<script stuff>|%{
    $Current = $_ # <= THIS LINE RIGHT HERE
    <more script stuff>|%{
        If($_ -match $Current){do stuff}
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top