powershellmergepscustomobject

Merge two PSCustomObject tables into a single one with PowerShell


I want to use PowerShell to merge two tables into one.

#Sample table
$CarList1 = @()
$CarList2 = @()

$CarList1 = [PSCustomObject]@{
    "Brand"           = "Audi";
    "Model"           = "A8";
    "Color"           = "Red";
    "ManufactureDate" = "2000.11.01"
}

$CarList2 = [PSCustomObject]@{
    "Brand"           = "Audi";
    "Model"           = "A4";
    "Color"           = "Green";
    "ManufactureDate" = "1998.11.01"
}

I want to transfer the data of $CarList2 into $CarList1

In the end I expect to have all the data in one table.

Brand Model Color ManufactureDate
----- ----- ----- ---------------
Audi  A8    Red   2000.11.01
Audi  A4    Green 1998.11.01

I have tried various things...

foreach ($property in $CarList2.psobject.Properties) {
    foreach ($array in $CarList2.$($property.Name)) {
        $CarList1.$($property.Name) += $array
    }
}
$CarList1 += $CarList2

...

I hope you could help me, I can't get it to work.


Solution

  • $CarList1 += $CarList2

    This only works if $CarList1 is already an array, which is not the case here, because, even though you tried to initialize it as an array with $CarList1 = @(), that initialization had no effect given that the subsequent $CarList1 = [PSCustomObject]@{ ... } assignment replaced the value with a single object.

    Without touching your other code, the simplest solution is to use a type constraint on your compound assignment, which implicitly converts $CarList1 to an array, if needed, and additionally ensures that any future values that get assigned are converted to an [array] ([object[]]) too, if necessary:

    # OK: Array concatenation, thanks to the [array] type constraint.
    [array] $CarList1 += $CarList2
    

    Note that in order for the + operator to perform array concatenation, it is sufficient for the LHS to be an array; if the RHS isn't, it is appended as single element to the output array; if it is, its elements are appended one by one.


    It follows from the above that if you had initialized (at least) $CarList1 with such a type constraint, $CarList1 += $CarList2 would have worked as-is:

    # Initialize the variables as empty arrays and *type-constrain* them as arrays.
    [array] $CarList1 = @()
    [array] $CarList2 = @()
    
    # Now, even assigning a *single* object causes an *array* to
    # be stored, with on-demand conversion.
    $CarList1 = [PSCustomObject]@{
        "Brand"           = "Audi";
        "Model"           = "A8";
        "Color"           = "Red";
        "ManufactureDate" = "2000.11.01"
    }
    
    # Ditto
    $CarList2 = [PSCustomObject]@{
        "Brand"           = "Audi";
        "Model"           = "A4";
        "Color"           = "Green";
        "ManufactureDate" = "1998.11.01"
    }
    
    # Since (at least) $CarList1 now is an array, array concatenation
    # now succeeds.
    $CarList1 += $CarList2
    

    Of course, in this example you could make do without the separate initialization statements, and just do: