powershell - find which hashtable key has value

Viewed 4512

I hardcoded a hashtable

$myHash = @{
    Americas = "US","CA","MX" #,...
    Asia = "CN","JP" #,...
    Europe = "PL","GB" #,...you get the idea

Now I'm going thru inputs in a foreach loop where I set

$country = $_.country #The 2-letter country code

Now I want to find if that country code maps to Americas, Asia, or Europe (aka which key holds that value). How can I find which key contains the 2-letter country code so I can have can have a variable/output that will say either Americas,Asia, or Europe (i.e $myVar = ??? prints/outputs "America"). I don't know powershell so I don't know the specific syntax to accomplish this

it looks like .containsValue() works on the hashtable itself, not a key of a hashtable. I with only 3 keys, I could just have 3 if statements

if($myHash["Americas"].containsValue()){ 
    $region = "Americas" 
    #or even better if I could get "Americas" dynamically by something like
    #$region = myHash.returnKeyThatContainsValue($country)
}
if($myHash["Asia"].containsValue()){...}
if($myHash["Europe"].containsValue()){...}
3 Answers

My fault. I didn't know you wanted a one liner.. This is the easiest way (requires PowerShell 5 I believe)

$myHash.GetEnumerator().Where({$_.Value -contains "US"})
#
Name                           Value                                                                                                                                     
----                           -----                                                                                                                                     
Americas                       {US, CA, MX}

If you just want the name:

$myHash.GetEnumerator().Where({$_.Value -contains "US"}).Name
#
Americas

"Old school" way:

$myHash.GetEnumerator() | Where {$_.Value -contains "US"}
## Q:\Test\2018\11\02\SO_53126357.ps1
$myHash = @{
    Americas = "US","CA","MX" 
    Asia = "CN","JP"
    Europe = "PL","GB","DE"
}

## array to lookup
$countries = @("CN","GB","US")

## look up with .GetEnumerator() to find the value
Foreach ($Country in $Countries){
    [PSCustomObject]@{
        Country = $Country
        Continent = ($myHash.GetEnumerator()|Where-Object Value -eq $Country).Name
    }
}

Country Continent
------- ---------
CN      Asia
GB      Europe
US      Americas

## or build the reverse hash as it's meant to be ...
$HashMy = @{}
ForEach ( $Item in $myHash.GetEnumerator()){
    $Item.Value|ForEach-Object {$HashMy[$_] = $Item.Name }
}
$HashMy

Name Value
---- -----
CA   Americas
CN   Asia
DE   Europe
GB   Europe
JP   Asia
MX   Americas
PL   Europe
US   Americas

## get value by key
Foreach ($Country in $Countries){
    "{0} = {1}" -f $Country,$HashMy.$Country
}

CN = Asia
GB = Europe
US = Americas

You could do something like this:

$myHash = @{
    Americas = "US","CA","MX" #,...
    Asia     = "CN","JP" #,...
    Europe   = "PL","GB"
}

foreach($key in $myHash.Keys){ 
    $value = $myHash[$key]
    foreach($val in $value){
        # if($val -eq "CN"){$key}
        Write-Host ("Key={0} Val={1}" -f $key,$val) -f Green
    }
}

And to take it a step further you could turn it into a function like:

function ConvertFromCountryCode-ToFriendlyName
{
    param(
        [Parameter(Mandatory=$true)]
        [ValidateLength(2,2)] #edit: changed (0,2) to (2,2)
        [string]$CountryCode
    )

    $myHash = @{
        Americas = "US","CA","MX" #,...
        Asia     = "CN","JP" #,...
        Europe   = "PL","GB"
    }

    $outString = $null
    foreach($key in $myHash.Keys){ 
        $value = $myHash[$key]
        foreach($val in $value){
            if($val -eq $CountryCode){ 
                $outString = $key
                # added break to speed it up
                break
            }
        }
    }

    if($outString -eq $null){ 
        Write-Host "Currently our database does not contain a friendly name for that country." -f Red 
    } else { 
        $outString 
    }

}

Which is used like:...

ConvertFromCountryCode-ToFriendlyName -CountryCode "US"

...and outputs:

Americas
Related