PowerShell:使用Group-Object对多属性PSObject分组去重
解决PowerShell PSObject数组分组合并冗余字段的问题
这个需求其实很常见,单纯用Group-Object确实达不到你要的结构——因为它返回的是分组信息对象,不是你需要的扁平化结构。我们需要在分组后手动重构每个组的对象,把重复的表头字段保留,把重复的文件信息打包成数组。
具体实现步骤
首先,先模拟你的原始PSObject数组(方便测试):
# 模拟原始数据 $originalBakObjects = @( [PSCustomObject]@{BakId=27; Name='DB_A'; Lsn=123; File='A_01'; Size=987}, [PSCustomObject]@{BakId=28; Name='DB_B'; Lsn=456; File='B_01'; Size=876}, [PSCustomObject]@{BakId=28; Name='DB_B'; Lsn=456; File='B_02'; Size=765}, [PSCustomObject]@{BakId=28; Name='DB_B'; Lsn=456; File='B_03'; Size=654} )
然后执行分组和对象重构:
$groupedResult = $originalBakObjects | # 按BakId、Lsn、Name三个字段分组,这三个字段相同的会被分到一组 Group-Object -Property BakId, Lsn, Name | ForEach-Object { # 提取当前组的共同属性(组内所有元素的这三个字段都一致,取第一个即可) $sharedProps = $_.Group[0] | Select-Object BakId, Lsn, Name # 把组内每个元素的File和Size打包成Files数组(这里给File加了.bak后缀,和你的示例匹配) $fileDetails = $_.Group | ForEach-Object { [PSCustomObject]@{ File = "$($_.File).bak" Size = $_.Size } } # 构建最终的目标对象 [PSCustomObject]@{ BakId = $sharedProps.BakId Lsn = $sharedProps.Lsn Name = $sharedProps.Name Files = $fileDetails } }
验证结果
执行完后,你可以用以下命令查看结构:
# 以列表形式查看详细结构 $groupedResult | Format-List # 或者转成JSON看更清晰的层级结构 $groupedResult | ConvertTo-Json -Depth 3
输出的JSON结构会和你期望的一致:
[ { "BakId": 27, "Lsn": 123, "Name": "DB_A", "Files": [ { "File": "A_01.bak", "Size": 987 } ] }, { "BakId": 28, "Lsn": 456, "Name": "DB_B", "Files": [ { "File": "B_01.bak", "Size": 876 }, { "File": "B_02.bak", "Size": 765 }, { "File": "B_03.bak", "Size": 654 } ] } ]
关键说明
Group-Object -Property BakId, Lsn, Name:这一步是核心,把三个字段完全相同的对象归为一组,确保我们不会遗漏任何需要合并的冗余信息。- 重构对象时,组内的共同属性只需要取第一个元素的值即可,因为分组依据就是这三个字段,组内所有元素的这三个值都是一致的。
- 如果不需要给
File字段加.bak后缀,直接把"$($_.File).bak"改成$_.File就行。
内容的提问来源于stack exchange,提问作者Chris Rodriguez
相关产品推荐
相关产品推荐

