I'm gathering information from an xml file and processing it. My queries are liberal in order to make sure I get all the possible elements I want. As a result, it's possible to end up with duplicate elements in the result list (called $components). I ran the result through Sort-Object and then Get-Unique to find all unique objects. It is my understanding that one of each unique object should be left by Get-Unique. But it's eliminating some of the already-unique objects (objects that have no duplicates in the original list).
Here is a simplified example. Just paste this into PowerShell or save to ps1 file and run (output shown below):
$xmlDoc = [xml]@'
<root>
<component Id='component1'>
<regkey Id='regkey1'/>
</component>
<component Id='component2'>
<file Id='file1' />
</component>
</root>
'@
$files = $xmlDoc.SelectNodes("//file[@Id='file1']")
$regkeys = $xmlDoc.SelectNodes("//regkey[@Id='regkey1']")
$components = $xmlDoc.SelectNodes("//component[@Id='component1'] | //component[@Id='component2']")
$components += $regkeys | Select-Object -ExpandProperty 'ParentNode'
$components | Sort-Object -Property 'Id'
Write-Host
$components | Sort-Object -Property 'Id' | Get-Unique
If you pasted into PowerShell, hit enter after that last line.
The output is like this:
PS C:\> $xmlDoc = [xml]@'
>> <root>
>> <component Id='component1'>
>> <regkey Id='regkey1'/>
>> </component>
>> <component Id='component2'>
>> <file Id='file1' />
>> </component>
>> </root>
>> '@
>>
PS C:\> $files = $xmlDoc.SelectNodes("//file[@Id='file1']")
PS C:\> $regkeys = $xmlDoc.SelectNodes("//regkey[@Id='regkey1']")
PS C:\> $components = $xmlDoc.SelectNodes("//component[@Id='component1'] | //component[@Id='component2
']")
PS C:\> $components += $regkeys | Select-Object -ExpandProperty 'ParentNode'
PS C:\> $components | Sort-Object -Property 'Id'
Id regkey
-- ------
component1 regkey
component1 regkey
component2
PS C:\> Write-Host
PS C:\> $components | Sort-Object -Property 'Id' | Get-Unique
Id regkey
-- ------
component1 regkey
PS C:\>
Notice how component2 disappears entirely once we pipe to Get-Unique. Can anyone explain this and offer a fix that keeps the query scheme about the same?
Edit: I assumed it would use the -eq operator to see if the elements were references to the same object in memory. If I manually try -eq it shows the correct objects being equal. But Get-Unique seems to be doing something else. If you add this code to the end of the above script it shows the object equivelance:
Write-Host
Write-Host "0: $($components[0].Id)"
Write-Host "1: $($components[1].Id)"
Write-Host "2: $($components[2].Id)"
Write-Host ("0 vs 1: " + ($components[0] -eq $components[1]))
Write-Host ("0 vs 2: " + ($components[0] -eq $components[2]))
Write-Host ("1 vs 2: " + ($components[1] -eq $components[2]))
The output (when run from script file):
0: component1
1: component2
2: component1
0 vs 1: False
0 vs 2: True
1 vs 2: False
You can use the -unique flag of sort-object. That gives the expected result for me:
$components | Sort-Object -Property 'Id' -Unique
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With