Powershell: Improve Compare-Object's default display format

Created on 17 Aug 2018  路  7Comments  路  Source: PowerShell/PowerShell

Compare-Object's output is insanely obscure. The very visually similar nature of <=, ==, and => make it both difficult to determine which is meant to be which (it's always hard to remember off-hand which "side" is -ReferenceObject and which is -DifferenceObject.

See below for a more illustrative example -- which still isn't perfect, but it's a step in the right direction. Arguably, the <= style symbols should be dropped completely and replaced with an [enum] that has values (names up for discussion) for ReferenceSet, DifferenceSet, and Both. If we want to provide an implicit conversion from the old strings to and from appropriate new enum values, that would smooth the transition and allow older scripts to perhaps still operate normally with them.

Fact of the matter is, as discussed in #4316 Compare-Object needs some love and some work. It's simply not programmatically useful in many ways. It literally just returns a PSCustomObject with some strings lazily indicating which set the values or objects came from, and it barely functions with complex objects, if at all.

It's really more of a Compare-Set than it is Compare-Object.

Steps to reproduce

> $Set1 = 1..20
> $Set2 = 1..40 | Where {$_ % 2 -eq 0}

> Compare-Object $Set1 $Set2 -IncludeEqual

Expected behavior

   OriginSet: Both

InputObject SideIndicator
----------- -------------
          2 ==
          4 ==
          6 ==
          8 ==
         10 ==
         12 ==
         14 ==
         16 ==
         18 ==
         20 ==


   OriginSet: DifferenceObject

InputObject SideIndicator
----------- -------------
         22 =>
         24 =>
         26 =>
         28 =>
         30 =>
         32 =>
         34 =>
         36 =>
         38 =>
         40 =>


   OriginSet: ReferenceObject

InputObject SideIndicator
----------- -------------
          1 <=
          3 <=
          5 <=
          7 <=
          9 <=
         11 <=
         13 <=
         15 <=
         17 <=
         19 <=

Actual behavior

InputObject SideIndicator
----------- -------------
          2 ==
          4 ==
          6 ==
          8 ==
         10 ==
         12 ==
         14 ==
         16 ==
         18 ==
         20 ==
         22 =>
         24 =>
         26 =>
         28 =>
         30 =>
         32 =>
         34 =>
         36 =>
         38 =>
         40 =>
          1 <=
          3 <=
          5 <=
          7 <=
          9 <=
         11 <=
         13 <=
         15 <=
         17 <=
         19 <=

Environment data

> $PSVersionTable
Name                           Value
----                           -----
PSVersion                      6.1.0-preview.3
PSEdition                      Core
GitCommitId                    v6.1.0-preview.3
OS                             Microsoft Windows 10.0.17134
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0
Area-Cmdlets-Utility Issue-Discussion Issue-Enhancement

Most helpful comment

I use Compare-Object extensively and is much better with -PassThru since that returns the original object referenced in the SideIndicator.

For this change, SideIndicator could be removed from the DefaultPropertySet so it still exists but not displayed. The new property could then be the [enum] with the desired values. That should prevent breaking scripts and make it easier for people to find the new property to use.

All 7 comments

It would also be nice to have a view that showed inline diff and side-by-side diff of the object (think of Format-List type output, but side by side)

Seems we can remove header "InputObject SideIndicator" but add a good header comment that we show in the group. After that we can remove SideIndicator column at all.

I avoid Compare-Object at the console because of this and welcome a change, however this would breaking change for all in my scripts.

I would much prefer a cmdlet that has a better feature set over not having to rewrite a few scripts. :)

Any other cmdlet, sure, we should worry about that. But imo, this one is so thoroughly not useful at the moment.

It is very useful to me and I'm sure to many others in its current state, it just has awkward console output as we all agree. Throw in collections of objects and you really will start to see it usefulness. At first I hated it too, and then realize the utility of it. At the console level I do avoid it but I shines at the script level which is where most of my enterpise PowerShell work is, hundreds of scripts if not more that use Compare-Object.

I use Compare-Object extensively and is much better with -PassThru since that returns the original object referenced in the SideIndicator.

For this change, SideIndicator could be removed from the DefaultPropertySet so it still exists but not displayed. The new property could then be the [enum] with the desired values. That should prevent breaking scripts and make it easier for people to find the new property to use.

Expected behavior

   Both  has (==):

InputObject
-----------
          2
          4
          6
          8
         10
         12
         14
         16
         18
         20


   DifferenceObject has (=>):

InputObject
-----------
         22
         24 
         26 
         28 
         30 
         32 
         34 
         36 
         38 
         40 


   ReferenceObject has (<=):

InputObject
-----------
          1
          3
          5
          7 
          9 
         11
         13
         15
         17 
         19 
Was this page helpful?
0 / 5 - 0 ratings