以 powershell 方式连接对象数组的属性

Joining the properties of an array of objects the powershell way

我有一个对象数组。

我想加入这些对象的属性,通常我会简单地这样做:

$Objs.prop1 -join(',')
$Objs.prop2 -join(',')
$Objs.prop3 -join(',')

但是对于这种情况,我想在加入它们之前对属性进行一些操作,这意味着我必须(希望有更强大的方法)这样做:

$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}
}

是否有一个漂亮的 PS 快捷方式来做这样的事情?

你的两个代码片段做不同的事情。假设您不想像第一个示例中那样在所有对象中加入相同的 属性,而是像在第二个示例中那样加入每个对象的属性,这应该做您想要的:

$objs | ForEach-Object {
  ($_.PSObject.Properties | ForEach-Object {
    [math]::Round($_.Value / 1MB)
  }) -join ','
}

如果您只需要选定的属性,您可以按名称过滤它们:

$propertyNames = 'prop1', 'prop2', 'prop3'

$objs | ForEach-Object {
  ($_.PSObject.Properties | Where-Object {
    $propertyNames -contains $_.Name
  } | ForEach-Object {
    [math]::Round($_.Value / 1MB)
  }) -join ','
}

或者在加入值之前使用自定义函数来处理这些值:

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 ','
}

首先,获取在属性之间使用逗号格式化的对象的一种非常直接的方法是使用 ConvertTo-Csv cmdlet,可从 PSv3 获得:

$Objs | Select prop1,prop2,prop3 | ConvertTo-Csv -NoTypeInformation

接下来,如果要转换属性,可以使用 Select-Object 和表达式:

$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

另一种方法是使用 Add-Member cmdlet 扩展您的原始对象。您可以添加新的计算属性:

$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)}}

这将为您提供 $Objs 上的三个额外属性,称为 Calc1|2|3,然后您可以将其转换为 CSV 格式:

$Objs | Select Calc1,Calc2,Calc3 | ConvertTo-Csv -NoTypeInformation