PSObject去重问题:Sort-Object处理重复数据失效求助
PowerShell哈希表数组去重问题解决
问题描述
我有一个包含重复条目的哈希表数组$ExistPreAnalysis,填充代码如下:
foreach ($all in $allFiles) { $Issql = 'false' if ($all.Extension -eq ".sql") { $Issql = 'true' } $dllpath = Convert-Path $all.PSPath $ParentCount = ($dllpath.Split([System.IO.Path]::DirectorySeparatorChar)).count for ($i = -2; $i -gt - $ParentCount; $i--) { $parentname = $dllpath.Split([System.IO.Path]::DirectorySeparatorChar)[$i] foreach ($r in $resultarray) { if ($parentname -match $r.PackageName) { foreach ($fil in $r.files) { $dll_name = ($fil.Split([System.IO.Path]::DirectorySeparatorChar)[-1]) if ($dll_name -like '${TargetRootFolder}*') { $dll_name = $dll_name.Replace('${TargetRootFolder}', '') } if ($Issql -eq 'true') { $nameTocompare = $all.name -replace ("%20", " ") } else { $nameTocompare = $all.name } if ($nameTocompare -match $dll_name) { $ExistPreAnalysis += @{ PackageName = $r.PackageName DllName = $dll_name Patch = $r.PatchNumber } } } } } } }
填充后$ExistPreAnalysis包含18条数据(实际应为9条唯一条目),重复的条目示例如下(每条Patch值对应重复一次):
Name Value ---- ----- DllName Pulling AD_Domain_Stored Procedures_PullAD-sp.sql Patch 1448763 PackageName IDUDatabase DllName Pulling AD_Domain_Stored Procedures_PullAD-sp.sql Patch 1485533 PackageName IDUDatabase ...(剩余重复条目省略)
我尝试了以下命令处理,但仅返回1条数据:
$ExistPreAnalysis = $ExistPreAnalysis | sort-Object -Unique -Property DllName, Patch, PackageName | Group-Object DllName | Where-Object { $_.Count -gt 1 } | ForEach-Object { $_.Group }
问题原因
- 数据类型不匹配:
$ExistPreAnalysis是哈希表(Hashtable)数组,而非PSObject。Sort-Object -Unique对哈希表的去重逻辑是比较对象引用,而非键值对内容,因此无法正确识别重复的哈希表条目。 - 过滤逻辑错误:后续的
Group-Object DllName | Where-Object { $_.Count -gt 1 }是筛选出现多次的分组,这会丢弃已去重的唯一条目,最终只保留重复组内的第一个元素。
正确解决方案
方案1:转换为PSObject后去重
先将哈希表数组转换为自定义PSObject,再基于属性进行去重:
# 转换为PSObject并去重 $ExistPreAnalysis = $ExistPreAnalysis | ForEach-Object { [PSCustomObject]$_ } | Sort-Object -Property DllName, Patch, PackageName -Unique
方案2:用Group-Object直接去重
通过分组后提取每组的第一个元素,实现去重:
$ExistPreAnalysis = $ExistPreAnalysis | Group-Object -Property DllName, Patch, PackageName | ForEach-Object { $_.Group[0] }
方案3:从源头避免重复
在填充数组时就检查条目是否已存在,避免添加重复项,提升整体效率:
# 修改填充代码中的添加逻辑 if ($nameTocompare -match $dll_name) { $newEntry = @{ PackageName = $r.PackageName DllName = $dll_name Patch = $r.PatchNumber } # 检查是否已有相同条目 $isDuplicate = $ExistPreAnalysis | Where-Object { $_.PackageName -eq $newEntry.PackageName -and $_.DllName -eq $newEntry.DllName -and $_.Patch -eq $newEntry.Patch } if (-not $isDuplicate) { $ExistPreAnalysis += $newEntry } }
验证结果
执行上述任一正确方案后,$ExistPreAnalysis将包含9条唯一数据,每条对应不同的Patch值。
内容的提问来源于stack exchange,提问作者Bandit
相关产品推荐
相关产品推荐

