Jacob Colvin
Jacob Colvin

Reputation: 2835

Is there a way to "Select * -Unique" with unique nested objects, without changing the objects?

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

Answers (2)

Jacob Colvin
Jacob Colvin

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

Mathias R. Jessen
Mathias R. Jessen

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

Related Questions