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.
CodePudding user response:
$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:
[array] $CarList1 = [pscustomobject] @{ ... }
, ...- or, if type-constraining isn't needed, you can use
@(...)
, the array-subexpression operator to ensure that your single object becomes an array:$CarList1 = @([pscustomobject] @{ ... })
CodePudding user response:
mklement0's answer is good, but I'd also like to raise awareness of PowerShell's array operator: @( ... )
. Anything you put inside is treated as an array.
$CarList1 = @($CarList1) $CarList2
In this case, rename your variables to $Car1 and $Car2 for the sake of sanity ;-)
Write-Output
is also a good one to be aware of:
$CarList = $Car1, $Car2 | Write-Output