Search code examples
powershellfor-loopvariablesindirection

Inserting for loop's variable into another variable names


I'm trying to simplify a Windows interface script that my colleague did in which he used a lot of if-loops which I think can be further shortened using for-loops.

Basically we have a couple sets of computers that ranged from 4 - 12 per set & we provide each admin an interface to revert their respective snapshots.

I'm looking to replace the number in each variable with the $i value from the for-loop.

I've tried using arrays & hashtables but based on what I've gathered, they're much more suitable in storing values & not formulas that included other variables.

if($ComputerNumber -eq 4) {
   $checkBoxComputer1LocX = $leftMargin
   $checkBoxComputer1LocY = [int]$labelSubHeaderLocY + [int]$buttonHeight + [int]$padding

   $checkBoxComputer2LocX = $leftMargin
   $checkBoxComputer2LocY = [int]$labelSubHeaderLocY + [int]$buttonHeight + [int]$padding + (1 * ([int]$checkBoxHeight + [int]$padding))

   $checkBoxComputer3LocX = $leftMargin
   $checkBoxComputer3LocY = [int]$labelSubHeaderLocY + [int]$buttonHeight + [int]$padding + (2 * ([int]$checkBoxHeight + [int]$padding))

   $checkBoxComputer4LocX = $leftMargin
   $checkBoxComputer4LocY = [int]$labelSubHeaderLocY + [int]$buttonHeight + [int]$padding + (3 * ([int]$checkBoxHeight + [int]$padding))
}

This is what I'm trying to achieve:

for($i=1; $i -le $ComputerNumber; i++) {
   $checkBoxComputer$iLocX = $leftMargin
   $checkBOxComputer$iLocY = [int]$labelSubHeaderLocY + [int]$buttonHeight + [int]$padding + (($i - 0) * ([int]$checkBoxHeight + [int]padding))
}

Solution

  • To use variable indirection (referring to a variable via its name stored in another variable) for assignment, use Set-Variable (for retrieval, you'd use Get-Variable):

    for($i=1; $i -le $ComputerNumber; i++) {
      Set-Variable -Name checkBoxComputer${i}LocX -Value $leftMargin
      Set-Variable -Name checkBoxComputer${i}LocY -Value ([int]$labelSubHeaderLocY + [int]$buttonHeight + [int]$padding + (($i - 0) * ([int]$checkBoxHeight + [int]padding)))
    }
    

    Note how the name of variable $i is enclosed in {...} (${i}) in order to unambiguously delineate it, so that the subsequent characters aren't considered part of the name.


    However, you can definitely use arrays and custom objects instead of individual variables, which is preferable:

    [array] $checkBoxes = for($i=1; $i -le $ComputerNumber; i++) {
      [pscustomobject] @{ 
         LocX = $leftMargin
         LocY= [int]$labelSubHeaderLocY + [int]$buttonHeight + [int]$padding + (($i - 0) * ([int]$checkBoxHeight + [int]padding))
      }
    }
    

    The above creates a (0-index-based) array of custom objects that each have a .LocX and .LocY property, so that, for instance, you can access the first checkbox's .LocX value as follows:

    $checkBoxes[0].LocX