Switch statement not matching all conditions

Viewed 66

I must be missing something here. I'm counting up a list, and want to skip over specific numbers, so I made a switch statement:

$locationNumber = 00
DO {
    $locationNumber++
    switch ($locationNumber) {
    21 {$locationNumber++}
    31 {$locationNumber++}
    43 {$locationNumber++}
    44 {$locationNumber++}
    49 {$locationNumber++}
    51 {$locationNumber++}
    }
    Write-Host $locationNumber
} while ($locationNumber -lt 53)

Here's the output:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 22 23 24 25 26 27 28 29 30 32 33 34 35 36 37 38 39 40 41 42 44 45 46 47 48 50 52 53

Notice that 44 shows up, even though I have no breaks. Can someone tell me why/a way around this?

Thanks,

EDIT: Added more code for context

3 Answers

What you probably want is the switches default clause.

If you move the Write-Host to default in the switch statement, this means that if the other conditions are not met, then default to this action.

$locationNumber = 00
DO {
    $locationNumber++
    switch ($locationNumber) {
    21 {}
    31 {}
    43 {}
    44 {}
    49 {}
    51 {}
    default {Write-Host $locationNumber}
    }
} while ($locationNumber -lt 53)

If you want to eliminate a fixed set of numbers - 21, 31, 43, 44, 49, 51 - from a series of numbers - 1 through 53:

$(
  switch (1..53) {
    { $_ -notin 21, 31, 43, 44, 49, 51 } { $_ }
  }
) -join ' '

The above yields (line-wrapped for readability) - note how all the numbers in the list above are missing:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 22 23 24 25 26 27 28 29
 30 32 33 34 35 36 37 38 39 40 41 42 45 46 47 48 50 52 53

To capture the numbers in an array, simply assign to a variable in lieu of the $(...):
$nums = switch { ... }

The above takes advantage of the following features:

  • .., the range operator, to create a series of integers as an array.

  • the switch statement accepting script blocks ({ ... }) as branch conditionals, in which the input object at hand, $_ can be tested via arbitrary expressions.

  • the -notin operator, which tests a scalar LHS for not being contained in a RHS collection.


As for what you tried:

By applying ++ to the numbers you wanted to skip, they were nonetheless printed by the Write-Host statement executed in the same iteration of the do statement, after the switch statement.

Andrew Ryan Davis' helpful answer shows a solution to that problem via the default branch. While the solution above is much more concise, Andrew's answer is actually faster, though that will likely not matter in practice.

Appreciate the help, but I just ended up doing

$locationNumber = 00
DO {
    $locationNumber++
    switch ($locationNumber) {
    21 {$locationNumber++}
    31 {$locationNumber++}
    43 {$locationNumber += 3}
    47 {$locationNumber++}
    49 {$locationNumber++}
    51 {$locationNumber++}
    }

    Write-Host $locationNumber
    
} while ($locationNumber -lt 53)

Where I added 3 to 43 to skip the ones I didn't need. Thanks.

Related