Skip to content

Suggestion: Improve Compare-Object by adding set operations (union, intersection, symmetric difference, relative complement) #4316

@mklement0

Description

@mklement0

This suggestion is the result of a conversation between @iSazonov and me - see #4293.

The idea is to introduce new parameter sets that:

  • frame the operations in the more established set-theory terms
  • while introducing the relative-complement operation to make it easy to determine the objects unique to one side.
  • make it easier to retrieve just the selected input objects (without the custom-object wrapper that contains the .SideIndicator property
  • improve the performance of certain use cases

Below are examples of each desired new parameter (parameter set) that would be mutually incompatible and also incompatible with the current parameter sets.

Aside from referring to the desired set operation, their desired behavior is expressed as s command using Compare-Object's current capabilities:

  • Compare-Object -Union $A $B: union (A ∪ B)

    Compare-Object $A $B -IncludeEqual -PassThru

  • Compare-Object -Intersection $A $B: intersection (A ∩ B):

    Compare-Object $A $B -IncludeEqual -ExcludeDifferent -PassThru

  • Compare-Object -SymmetricDifference $A $B: symmetric difference (A ∆ B) - the same as the current default behavior, but without the wrapper objects

    Compare-Object $A $B -PassThru

  • Compare-Object -Complement $A $B: relative complement (A ∖ B) - getting objects unique to $B

    Compare-Object $A $B | ? SideIndicator -eq '=>' | % InputObject

Syntax note: @dragonwolf83 proposes using a single parameter such as -SetOperation <operation> (e.g., -SetOperation Intersection or -SetOperation Union) instead of distinct switches (e.g., -Intersection or -Union), which makes for easier implementation (no need for a distinct parameter set for each operation) and better discoverability, though is slightly more cumbersome to type for experienced users who already know what they want.

Note that all commands above (effectively) suppress the custom-object wrapper with the .SideIndicator property and return the selected input objects directly (or, with -Property specified, the resulting [pscustomobject] instance would lack the .SideIndicator property).

One thing to note is the order in which objects are output - this is not currently documented (from a set perspective, order doesn't matter, but for subsequent processing it may), and I haven't dug into the source to verify, but from what I can tell, it is:

  • == (identical) objects first
  • >= right-side-only objects next
  • <= left-side-only objects last

On a related note, adding a new switch would make sense in order to return a hashtable of original objects grouped by what is currently the .SideIndicator value.

Two names have been proposed for this switch:

  • -Group
  • -AsHashtable

-AsHashtable has the advantage of being familiar from Group-Object, although there it doesn't indicate a fundamental change in output structure.

The following example uses -Group for now:

$A = 1, 2, 3, 4
$B = 1, 3, 4, 5

# Wishful thinking
Compare-Object -Group -Union $A $B

The above would yield the equivalent of:

@{
  '==' = 1, 3, 4
  '<=' = , 2
  '=>' = , 5
}

Environment data

PowerShell Core v6.0.0-beta.4

Metadata

Metadata

Assignees

No one assigned

    Labels

    Issue-Enhancementthe issue is more of a feature request than a bugResolution-No ActivityIssue has had no activity for 6 months or moreWG-Cmdletsgeneral cmdlet issues

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions