Created
April 14, 2023 22:18
-
-
Save Jaykul/f55f8418c6d03d426891dfaa5b424ac6 to your computer and use it in GitHub Desktop.
Expand and Group objects when they have (or could be deduped with) a single array property
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
filter Expand-Property { | |
<# | |
.SYNOPSIS | |
Expands an array property, creating a duplicate object for each value | |
.EXAMPLE | |
[PSCustomObject]@{ Name = "A"; Value = @(1,2,3) } | Expand-Property Value | |
Name Value | |
---- ----- | |
A 1 | |
A 2 | |
A 3 | |
.EXAMPLE | |
[PSCustomObject]@{ | |
Name = "DevOps" | |
Members = "Joe", "Phil", "Barb" | |
MemberOf = "Ops", "Dev" | |
} | | |
Expand-Property MemberOf | | |
Expand-Property Members | |
Name MemberOf Members | |
---- -------- ------- | |
DevOps Ops Joe | |
DevOps Ops Phil | |
DevOps Ops Barb | |
DevOps Dev Joe | |
DevOps Dev Phil | |
DevOps Dev Barb | |
#> | |
param( | |
# The name of a property on the input object, that has more than one value | |
[Alias("Property")] | |
[string]$Name, | |
# The input object to duplicated | |
[Parameter(ValueFromPipeline)] | |
$InputObject | |
) | |
foreach ($Value in $InputObject.$Name) { | |
$InputObject | Select-Object *, @{ Name = $Name; Expr = { $Value } } -Exclude $Name | |
} | |
} | |
function Group-Property { | |
<# | |
.SYNOPSIS | |
Given a collection of objects with where only one property differs, | |
returns a single object with an array property containing the values | |
.EXAMPLE | |
@( | |
[PSCustomObject]@{ Name = "A"; Value = 1 } | |
[PSCustomObject]@{ Name = "A"; Value = 2 } | |
[PSCustomObject]@{ Name = "A"; Value = 3 } | |
) | Group-Property Value | |
Name Value | |
---- ----- | |
A {1, 2, 3} | |
.EXAMPLE | |
@" | |
Name,MemberOf,Members | |
DevOps,Ops,Joe | |
DevOps,Ops,Phil | |
DevOps,Ops,Barb | |
DevOps,Dev,Joe | |
DevOps,Dev,Phil | |
DevOps,Dev,Barb | |
"@ | ConvertFrom-Csv | Group-Property Members | Group-Property MemberOf | |
Name MemberOf Members | |
---- -------- ------- | |
DevOps {Ops, Dev} {Barb, Joe, Phil} | |
#> | |
[CmdletBinding()] | |
param( | |
# The input objects to deduplicated | |
[Parameter(ValueFromPipeline)] | |
[psobject] | |
${InputObject}, | |
# The name of the property that has unique values | |
[Parameter(Position = 0)] | |
[string] | |
${Name}, | |
# Specifies the culture to use when comparing strings. | |
[string] | |
${Culture}, | |
# Indicates that the grouping is case-sensitive. Without this parameter, the property values of objects in a group might have different cases. | |
[switch] | |
${CaseSensitive} | |
) | |
begin { | |
try { | |
$outBuffer = $null | |
$null = $PSBoundParameters.Remove("Name") | |
if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer)) { | |
$PSBoundParameters['OutBuffer'] = 1 | |
} | |
$wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Microsoft.PowerShell.Utility\Group-Object', [System.Management.Automation.CommandTypes]::Cmdlet) | |
} catch { | |
throw | |
} | |
} | |
process { | |
try { | |
if (!$steppablePipeline) { | |
$PSBoundParameters["Property"] = $InputObject.PSObject.Properties.Name.Where{ $_ -ne $Name } | |
$null = $PSBoundParameters.Remove("InputObject") | |
Write-Verbose "Group by $($PSBoundParameters["Property"] -join ', ')" | |
$scriptCmd = { & $wrappedCmd @PSBoundParameters | ForEach-Object { $_.Group[0].$Name = $_.Group.$Name; $_.Group[0] } } | |
$steppablePipeline = $scriptCmd.GetSteppablePipeline($myInvocation.CommandOrigin) | |
$steppablePipeline.Begin($PSCmdlet) | |
} | |
$steppablePipeline.Process($_) | |
} catch { | |
throw | |
} | |
} | |
end { | |
try { | |
$steppablePipeline.End() | |
} catch { | |
throw | |
} | |
} | |
clean { | |
if ($null -ne $steppablePipeline) { | |
$steppablePipeline.Clean() | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment