Skip to content

Commit 76dec0d

Browse files
committed
✨ Add Measure-Properties.ps1
- resolves brianary#60
1 parent 1acd76b commit 76dec0d

File tree

1 file changed

+107
-0
lines changed

1 file changed

+107
-0
lines changed

Measure-Properties.ps1

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
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

Comments
 (0)