I have an array of objects, which have the property of p1, p2, p3, p4
.
$objectArray = [PSCustomObject]@{
p1 = "Value1"; p2 = "Value2"; p3 = "Value3"; p4 = "Value4"
},[PSCustomObject]@{
p1 = "Value5"; p2 = "Value6"; p3 = "Value7"; p4 = "Value8"
}
And I have a property-name-mapping hashtable, for example
$propertyReplacements = @{
"p1" = "x1"
"p2" = "y1"
}
How to select only the properties which exist in the keys of hash table $propertyReplacements
; and rename the property name to the values in the hash table?
The result will be
[PSCustomObject]@{
x1 = "Value1"; y1 = "Value2";
},[PSCustomObject]@{
x1 = "Value5"; y1 = "Value6";
}
The properties filtering can be
$objectArray | select -Property @($propertyReplacements.Keys) |
....
CodePudding user response:
The following uses an ordered dictionary and casting [pscustomobject]
to create new objects, I really don't think Select-Object
is the proper tool for this.
# use a temporary ordered dictionary
$tmp = [ordered]@{}
# enumerate each object
foreach($obj in $objectArray) {
# store the PSMemberInfoIntegratingCollection for later access
$properties = $obj.PSObject.Properties
# enumerate the hash keys
foreach($key in $propertyReplacements.Keys) {
# if the hash key exists as property Name in this object
if($prop = $properties.Item($key)) {
# create a new property Name using the Value of the hashtable
# and keep the current Value of the value
$tmp[$propertyReplacements[$prop.Name]] = $prop.Value
}
}
# create a new object casting this type accelerator
[pscustomobject] $tmp
# and clear the dictionary for the next object
$tmp.Clear()
}
CodePudding user response:
Here is another solution
foreach($k in $propertyReplacements.Keys) {
if ($k -ne $propertyReplacements.$k) {
$objectArray = $objectArray | select *,{n=$propertyReplacements.$k; $e={$_.$k}}
$objectArray = $objectArray | select -ExcludeProperty $k
}
}
# $objectArray has updated property names now