Reputation: 31530
I have an array of objects.
I would like to join the properties of these objects and normally I would simply do this:
$Objs.prop1 -join(',')
$Objs.prop2 -join(',')
$Objs.prop3 -join(',')
But for this case I want to do some manipulation of the properties before I join them which means I have to (hoping there is a more powershelly way) do this:
$ArrObj = @()
foreach ($obj in $objs) {
$calcProp1 = [math]::Round($obj.prop1 / 1MB)
$calcProp2 = [math]::Round($obj.prop2 / 1MB)
$calcProp3 = [math]::Round($obj.prop3 / 1MB)
$ArrObj += [string]$clacProp1+','+$clacProp2+','+$clacProp3}
}
Is there a nifty PS shortcut for doing something like this?
Upvotes: 2
Views: 10554
Reputation: 4659
Firstly, one pretty direct way to get an object formatted with commas between properties is to use the ConvertTo-Csv
cmdlet, available from PSv3:
$Objs | Select prop1,prop2,prop3 | ConvertTo-Csv -NoTypeInformation
Next, if you want to convert properties, you could use Select-Object
with expressions:
$Objs | Select-Object -Property `
@{Label="Calc1";Value={[math]::Round($_.prop1 / 1MB)}} `
@{Label="Calc2";Value={[math]::Round($_.prop2 / 1MB)}} `
@{Label="Calc3";Value={[math]::Round($_.prop3 / 1MB)}} `
| ConvertTo-Csv -NoTypeInformation
A different tack could be to extend your original object using the Add-Member
cmdlet. You can add new calculated properties:
$Objs | Add-Member -MemberType ScriptProperty -Name "Calc1" -Value {[math]::Round($_.prop1 / 1MB)}}
$Objs | Add-Member -MemberType ScriptProperty -Name "Calc2" -Value {[math]::Round($_.prop2 / 1MB)}}
$Objs | Add-Member -MemberType ScriptProperty -Name "Calc3" -Value {[math]::Round($_.prop3 / 1MB)}}
This will give you three additional properties on $Objs called Calc1|2|3, which you can then convert to CSV format:
$Objs | Select Calc1,Calc2,Calc3 | ConvertTo-Csv -NoTypeInformation
Upvotes: 0
Reputation: 200203
Your two code snippets do different things. Assuming that you don't want want to join the same property across all objects as in your first example, but rather join properties per object as in your second example this should do what you want:
$objs | ForEach-Object {
($_.PSObject.Properties | ForEach-Object {
[math]::Round($_.Value / 1MB)
}) -join ','
}
If you want just selected properties you can filter them by name:
$propertyNames = 'prop1', 'prop2', 'prop3'
$objs | ForEach-Object {
($_.PSObject.Properties | Where-Object {
$propertyNames -contains $_.Name
} | ForEach-Object {
[math]::Round($_.Value / 1MB)
}) -join ','
}
or use a custom function for manipulating the values before joining them:
function Convert-PropertyValue {
[CmdletBinding()]
Param(
[Parameter(Mandatory=$true, Position=0, ValueFromPipeline=$true)]
[Management.Automation.PSPropertyInfo]$Property
)
Process {
switch ($Property.Name) {
'prop1' { [math]::Round($Property.Value / 1MB) }
'prop2' { $Property.Value + 42 }
'prop3' { 'Value: {0:d3}' -f $Property.Value }
default { $Property.Value }
}
}
}
$objs | ForEach-Object {
($_.PSObject.Properties | Convert-PropertyValue) -join ','
}
Upvotes: 3