LPChip
LPChip

Reputation: 884

Count in multidimensional array using Powershell

I query users in Office365 and need to count how many licenses they have based on what domain their UserPrincipalName has. In order to make it easier to troubleshoot, I've created a new script that focuses solely on the problem, but I can't get it to work even there.

Here's my script:

#$users = get-msoluser -TenantId $customer.TenantId -All | Where-Object {$_.islicensed} | Sort-Object UserPrincipalName
$users = @(
    [pscustomobject]@{
        name='User1'
        domain='domain1'
        license='A'
    }
    [pscustomobject]@{
        name='User2'
        domain='domain2'
        license='A', 'B'
    }
    [pscustomobject]@{
        name='User3'
        domain='domain1'
        license='A', 'B'
    }
    [pscustomobject]@{
        name='User4'
        domain='domain1'
        license='B'
    }
    [pscustomobject]@{
        name='User5'
        domain='domain2'
        license='A'
    }
    [pscustomobject]@{
        name='User6'
        domain='domain1'
        license='B'
    }
    [pscustomobject]@{
        name='User7'
        domain='domain1'
        license='A','B'
    }
)

$domains = 'domain1','domain2'

$users |fl *
$domains |fl

$LicenseCounting = @{}

$domains | foreach-object {
    $LicenseCounting[$_] = @{}

}

foreach($user in $users)
{
    $licenses = @()
    $user.license | foreach-object {
        $licenses += $_
    }
    $LicenseCounting[$domains][$licenses] = $LicenseCounting[$domains][$licenses] + 1

}

$LicenseCounting | fl *

<# expected result: 
$licenseCounting[domain1][A]=3
$licenseCounting[domain1][B]=4
$licenseCounting[domain2][A]=2
$licenseCounting[domain2][B]=1

#>

output:


name    : User1
domain  : domain1
license : A

name    : User2
domain  : domain2
license : {A, B}

name    : User3
domain  : domain1
license : {A, B}

name    : User4
domain  : domain1
license : B

name    : User5
domain  : domain2
license : A

name    : User6
domain  : domain1
license : B

name    : User7
domain  : domain1
license : {A, B}



domain1
domain2
Cannot convert the "System.Object[]" value of type "System.Object[]" to type "System.Int32"
.
At C:\Users\xxxxxxx\Documents\array count test.ps1:58 char:5
+     $LicenseCounting[$domains][$licenses] = $LicenseCounting[$domains ...
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [], RuntimeException
    + FullyQualifiedErrorId : ConvertToFinalInvalidCastException
 
Cannot convert the "System.Object[]" value of type "System.Object[]" to type "System.Int32"
.
At C:\Users\xxxxxxx\Documents\array count test.ps1:58 char:5
+     $LicenseCounting[$domains][$licenses] = $LicenseCounting[$domains ...
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [], RuntimeException
    + FullyQualifiedErrorId : ConvertToFinalInvalidCastException
 
Cannot convert the "System.Object[]" value of type "System.Object[]" to type "System.Int32"
.
At C:\Users\xxxxxxx\Documents\array count test.ps1:58 char:5
+     $LicenseCounting[$domains][$licenses] = $LicenseCounting[$domains ...
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [], RuntimeException
    + FullyQualifiedErrorId : ConvertToFinalInvalidCastException
 
Cannot convert the "System.Object[]" value of type "System.Object[]" to type "System.Int32"
.
At C:\Users\xxxxxxx\Documents\array count test.ps1:58 char:5
+     $LicenseCounting[$domains][$licenses] = $LicenseCounting[$domains ...
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [], RuntimeException
    + FullyQualifiedErrorId : ConvertToFinalInvalidCastException
 
Cannot convert the "System.Object[]" value of type "System.Object[]" to type "System.Int32"
.
At C:\Users\xxxxxxx\Documents\array count test.ps1:58 char:5
+     $LicenseCounting[$domains][$licenses] = $LicenseCounting[$domains ...
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [], RuntimeException
    + FullyQualifiedErrorId : ConvertToFinalInvalidCastException
 
Cannot convert the "System.Object[]" value of type "System.Object[]" to type "System.Int32"
.
At C:\Users\xxxxxxx\Documents\array count test.ps1:58 char:5
+     $LicenseCounting[$domains][$licenses] = $LicenseCounting[$domains ...
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [], RuntimeException
    + FullyQualifiedErrorId : ConvertToFinalInvalidCastException
 
Cannot convert the "System.Object[]" value of type "System.Object[]" to type "System.Int32"
.
At C:\Users\xxxxxxx\Documents\array count test.ps1:58 char:5
+     $LicenseCounting[$domains][$licenses] = $LicenseCounting[$domains ...
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [], RuntimeException
    + FullyQualifiedErrorId : ConvertToFinalInvalidCastException
 


Name  : domain2
Key   : domain2
Value : {}

Name  : domain1
Key   : domain1
Value : {}

In my example, I'm getting an error. When I use the first row that is commented out, it actually does work, but instead of counting, it puts all licenses in a string: eg, 'A', 'A', 'B', 'A'... etc. I'm sure once I get it to work in my example, I can get it to work in the real case too.

Upvotes: 0

Views: 163

Answers (1)

Mathias R. Jessen
Mathias R. Jessen

Reputation: 174545

You need to reference specific domain and license identifier values when assigning to your hashtable:

$licenseCount = @{}

foreach($user in $users){
  # Create top-level per-domain hashtable for $user.domain if it doesn't already exist
  if(-not $licenseCount.ContainsKey($user.domain)){
    $licenseCount[$user.domain] = @{}
  }

  $user.license |ForEach-Object {
    # Count each license type separately, store in previously created per-domain hashtable
    $licenseCount[$user.domain][$_] += 1
  }
}

$licenseCount will now have been populated with the information as described in your post:

PS ~> $licenseCount['domain2']['A']
2

Upvotes: 2

Related Questions