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
.
> $Set1 = 1..20
> $Set2 = 1..40 | Where {$_ % 2 -eq 0}
> Compare-Object $Set1 $Set2 -IncludeEqual
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 <=
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 <=
> $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
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.
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
Most helpful comment
I use
Compare-Object
extensively and is much better with-PassThru
since that returns the original object referenced in theSideIndicator
.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.