powershellfor-loopswitch-statement

Unexpected Data type behavior in PowerShell


I'm relatively new in Powershell. I've tried to combine Foreach with Switch and Data type checking.

$collection = @{A = 1; B="abc"; C = 33; D = "44" }

foreach($key in $collection.Keys){
  switch ( ($collection.$key).GetType() ){
    { $_ -eq [int32]} {Write-Output "It's an integer"; break}
    { $_ -eq [string]} {Write-Output "It's a string"; break}
  }
}

#Second attempt

foreach($key in $collection.Keys){
  switch ($collection.$key.GetType()){
    {$PSItem -eq [System.Int32]} {Write-Host "It's an integer"; break}
    {$PSItem -eq [System.String]} {Write-Host "It's a string"; break}
  }
}

The result I'm getting for both is:

It's an integer It's a string It's a string It's an integer

I've tried to cast the data type or using the -is comparison

I don't want to use if but understand what I'm missing.

Someone can tell me why?


Solution

  • $Collection is a [Hashtable].
    Hashtables do NOT preserve the order of the keys.

    You need to use a [Ordered] dictionary for that:

    $collection = [ordered]@{A = 1; B = "abc"; C = 33; D = "44"; W = 9.9 }
    
    foreach ($key in $collection.Keys) {
        write-host "Key '$key' is " -NoNewline
        switch ( $Collection.$key ) {
            { $_ -is [Int32] } { write-host "an [integer]"; break }
            { $_ -is [string] } { write-host "a [string]"; break }
            default { Write-Host "not a [String] or [Int]. It's a [$($_.gettype())]" }
        }
    }
    

    result:

    Key 'A' is an [integer]
    Key 'B' is a [string]
    Key 'C' is an [integer]
    Key 'D' is a [string]
    Key 'W' is not a [String] or [Int]. It's a [double]
    

    as you can see,l Ordered Dictionaries are, basically, "Hashtable that preserve the order of the keys"