|
| 1 | +<# |
| 2 | +.SYNOPSIS |
| 3 | +Provides frequency details about the properties across objects in the pipeline. |
| 4 | +
|
| 5 | +.INPUTS |
| 6 | +System.Object values to be analyzed in aggregate. |
| 7 | +
|
| 8 | +.OUTPUTS |
| 9 | +System.Management.Automation.PSCustomObject that describes the properties of the objects: |
| 10 | +* PropertyName |
| 11 | +* Type |
| 12 | +* Unique |
| 13 | +* Nulls |
| 14 | +* Values |
| 15 | +* Minimum |
| 16 | +* Maximum |
| 17 | +
|
| 18 | +.FUNCTIONALITY |
| 19 | +Data |
| 20 | +
|
| 21 | +.LINK |
| 22 | +Write-Info.ps1 |
| 23 | +
|
| 24 | +.LINK |
| 25 | +Stop-ThrowError.ps1 |
| 26 | +
|
| 27 | +.EXAMPLE |
| 28 | +Get-PSDrive |Measure-Properties.ps1 |Format-Table -AutoSize |
| 29 | +
|
| 30 | +Type: System.Management.Automation.PSDriveInfo |
| 31 | +Count: 13 |
| 32 | +
|
| 33 | +PropertyName Type Unique Nulls Values Minimum Maximum |
| 34 | +------------ ---- ------ ----- ------ ------- ------- |
| 35 | +Used System.Object False 12 1 219129761792.00 219129761792.00 |
| 36 | +Free System.Object False 12 1 803764846592.00 803764846592.00 |
| 37 | +CurrentLocation System.String False 11 2 Users\brian |
| 38 | +Name System.String True 0 13 A WSMan |
| 39 | +Root System.String False 4 9 \ SQLSERVER:\ |
| 40 | +Description System.String False 1 12 X509 Certificate Provider |
| 41 | +VolumeSeparatedByColon System.Boolean False 12 1 1.00 1.00 |
| 42 | +#> |
| 43 | + |
| 44 | +#Requires -Version 7 |
| 45 | +[CmdletBinding()] Param( |
| 46 | +[Parameter(ValueFromPipeline=$true)] $InputObject |
| 47 | +) |
| 48 | +Begin |
| 49 | +{ |
| 50 | + $typename = New-Object Collections.Generic.HashSet[string] |
| 51 | + [long] $count = 0 |
| 52 | + $type = [ordered]@{} |
| 53 | + $nullvalue = [ordered]@{} |
| 54 | + $value = [ordered]@{} |
| 55 | +} |
| 56 | +Process |
| 57 | +{ |
| 58 | + [void]$typename.Add($null -eq $InputObject ? '(null)' : $InputObject.GetType().FullName) |
| 59 | + $count++ |
| 60 | + foreach($property in $InputObject.PSObject.Properties) |
| 61 | + { |
| 62 | + $propname,$propvalue,$proptype = $property.Name,$property.Value,$property.TypeNameOfValue |
| 63 | + if($propvalue -isnot [icomparable]) {continue} |
| 64 | + if(!$type.Contains($propname)) {$type[$propname] = $proptype} |
| 65 | + if(!$nullvalue.Contains($propname)) {$nullvalue[$propname] = 0} |
| 66 | + if($null -eq $propvalue) |
| 67 | + { |
| 68 | + $nullvalue[$propname]++ |
| 69 | + } |
| 70 | + elseif($value.Contains($propname)) |
| 71 | + { |
| 72 | + if($proptype -ne $type[$propname]) |
| 73 | + { |
| 74 | + Stop-ThrowError.ps1 "Property '$propname' has conflicting types: '$($type[$propname])' vs '$proptype'" -Argument InputObject |
| 75 | + } |
| 76 | + $value[$propname] += $propvalue |
| 77 | + } |
| 78 | + else |
| 79 | + { |
| 80 | + $value[$propname] = @($propvalue) |
| 81 | + } |
| 82 | + } |
| 83 | +} |
| 84 | +End |
| 85 | +{ |
| 86 | + Write-Info.ps1 'Type: ' -fg Green -NoNewLine |
| 87 | + Write-Info.ps1 ($typename.GetEnumerator() -join ', ') -fg Gray |
| 88 | + Write-Info.ps1 'Count: ' -fg Green -NoNewLine |
| 89 | + Write-Info.ps1 $count -fg Gray |
| 90 | + foreach($propname in $value.Keys) |
| 91 | + { |
| 92 | + $uniquevalues = @($value[$propname] |Select-Object -Unique).Count |
| 93 | + #TODO: detect numeric types for stats |
| 94 | + $stats = $value[$propname] |Measure-Object -Minimum -Maximum |
| 95 | + #TODO: detect stringc type for length stats |
| 96 | + #TODO: detect datetime types for expanded stats? |
| 97 | + [pscustomobject]@{ |
| 98 | + PropertyName = $propname |
| 99 | + Type = $type[$propname] |
| 100 | + Unique = $count -eq $uniquevalues |
| 101 | + Nulls = $count - $uniquevalues |
| 102 | + Values = $uniquevalues |
| 103 | + Minimum = $stats.Minimum |
| 104 | + Maximum = $stats.Maximum |
| 105 | + } |
| 106 | + } |
| 107 | +} |
0 commit comments