Home > Net >  Iterate through hashable containing list of values and iterate through each value in the list
Iterate through hashable containing list of values and iterate through each value in the list

Time:09-02

I am working on a script I can run that will take a list of users and their allocated licenses and filter them based on their UPN to get a count of license usage per sub domain as a representation of the total licenses.

I have sorted them into hash tables based on the domain in their UPN.

$org1Users  = [PSCustomObject]@{
            UserPrincipalName = $user.UserPrincipalName
            AccountSkuId = $user.Licenses

With those hash tables each contains the UPN and the Licenses string for each user displayed as:

UserprincipalName            Licenses
-----------------                      --------
[email protected]        {org:STREAM, org:ENTERPRISEPACK}

I am trying to figure out how I can iterate through each user in the hashtable and split out their licenses so that I can do a switch or if/else chain of "if they have x license" increment the count of *License_Type" in another Hashtable. As it is it will only do it once per user which doesn't work if they have Multiple Licenses.

foreach($user in $AGUsers)
{
If($AGUsers.AccountSkuId -eq 'owfg:VISIOCLIENT')
    {
        $ConsumedLicenses[$VISIOCLIENT]  
    }
    elseif ($AGUsers.AccountSkuId -eq "owfg:STREAM" ) {
        $ConsumedLicenses[$STREAM]  
    }
.....onwards

At the end I will be taking the values from the License_Type hash tables and using the individual values to generate a report breaking down the % of the total count of licenses each domain is consuming.

CodePudding user response:

Given the structure of the data, you'll probably need two loops to "pivot" the data, and one loop to determine percentages.

The first loop should go over each user.

The second loop should go over each license.

Personally, I'd use another hashtable to "pivot" the data so that you end up with a hashtable of licenses and users. I'd also keep track of the total as I go, because that saves the effort of doing it later when calculating a percentage.

$licenseTotal = 0
$groupedByLicense = @{}
foreach ($user in $agusers) {
   foreach ($userLicense in $agUsers.AccountSkuID) {
       if (-not $groupedByLicense[$userLicense]) {
           $groupedByLicense[$userLicense] = @()
       }
       $groupedByLicense[$userLicense]  = $user
       $licenseTotal  
   }
}

# In the second loop, we'll walk over each key/value in a Hashtable.
# To do this, you'll want to use .GetEnumerator
$licensePercentage = @{}
foreach ($keyValuePair in $groupedByLicense.GetEnumerator()) {
    $licensePercentage[$keyValuePair.Key] = # FYI
       # you can break assignments into multiple lines
       $keyValuePair.Value.Length / 
       # comments can exist after an operator
       $licenseTotal

}

[PSCustomObject]$LicensePercentage

CodePudding user response:

  • Terminology note: [PSCustomObject]@{ ... } is a custom-object literal, not a hashtable. That is, even though this form of syntactic sugar is based on a hashtable literal, it constructs a [pscustomobject] instance.

  • To test if an array of values contains a value of interest (based on equality testing, i.e. per-element -eq tests), use the -containsoperator.

Thus, you're probably looking for something like this:

switch ($AGUsers)
{
  { $_.AccountSkuId -contains 'owfg:VISIOCLIENT' } { $ConsumedLicenses[$VISIOCLIENT]   }
  { $_.AccountSkuId -contains 'owfg:STREAM' }      { $ConsumedLicenses[$STREAM]   }
  # ...
}

Note that - unlike an if ... elseif ... statement - the conditionals of a switch statement are all evaluated by default, unless you short-circuit processing with continue (if you were to use break all remaining $AGUsers elements would be skipped).

  • Related