Reputation: 2835
Suppose I have the following:
$x = @()
$x += [pscustomobject]@{
a=1
b=2
c=[pscustomobject]@{
a=1
b=2
}
}
$x += [pscustomobject]@{
a=1
b=2
c=[pscustomobject]@{
a=3
b=4
}
}
$x | Select * -Unique
My desired behaviour would be to return both objects inside $x
, since $x.c
contains unique items. I cannot simply run $x.c | Select * -Unique
because I want to store and associate the entire object.
The above code, regardless of the exact objects, simply returns the first object.
Is there a way to produce my desired behaviour without just flattening all my objects?
Potential very messy solution using invoke-expression:
$a = $x | gm | ? {$_.MemberType -eq 'NoteProperty' -and $_.Definition -like '*object*'} | select -ExpandProperty Name
$y = @()
$a | %{
$p = $_
$x.$p | gm | ? {$_.MemberType -eq 'NoteProperty'} | select -ExpandProperty Name | % { $y += "{`$_.$p.$_}" }
}
$y = ($y | convertto-json -Compress) -replace '\[' -replace '\]' -replace '\"'
iex -command ('$x | Sort (iex $y) -Unique |Select *')
Upvotes: 1
Views: 445
Reputation: 2835
I came up with this armed with the knowledge that sort-object can distinguish properties using scriptblocks. I essentially just pull all the properties I'm interested in, create the script block, and add that to an array.
$itemsToExpand = $x | Get-Member | Where-Object {$_.MemberType -eq 'NoteProperty' -and $_.Definition -like '*object*'} | Select-Object -ExpandProperty Name
$scriptBlockArray = @()
$itemsToExpand | ForEach-Object{
$current = $_
$x.$current | Get-Member | Where-Object {$_.MemberType -eq 'NoteProperty'} | Select-Object -ExpandProperty Name | ForEach-Object {
$scriptBlockArray += [Scriptblock]::Create("`$_.$current.$_")
}
}
$x | Sort-Object $scriptBlockArray -Unique
Upvotes: 0
Reputation: 174575
If you want to distinguish the properties of c
, use Sort-Object
first:
$x |Sort {$_.c.a},{$_.c.b} -Unique |Select *
Upvotes: 1