PowerShell中PSCustomObject仅保留最后写入值问题求助
问题分析与解决
核心结论
PSCustomObject的使用方式本身是合适的,问题出在变量赋值逻辑上——你每次匹配时都直接覆盖了$result变量,没有把新创建的对象添加到集合中,所以最后只保留了最后一组匹配结果。
错误原因
代码中每次进入if分支时,执行的是$result = [pscustomobject]@{...}:这会让$result变量指向新创建的对象,之前存储的匹配对象会被直接丢弃,自然只剩最后一次的结果。
修正方案
需要先初始化一个空集合(数组或泛型列表),每次匹配时把新的PSCustomObject添加到集合里,而非覆盖变量。
方案1:使用数组(适合小数据量场景)
先初始化空数组,匹配时用+=操作添加元素:
# 初始化空数组存储结果 $result = @() for ($i = 0; $i -lt $array.length; $i++) { $cfID = $array[$i].substring(65, 16) for ($j = 0; $j -lt $slotnames.length; $j++) { if ($slotnames[$j].deviceID.substring(22, 16) -eq $cfID) { # 向数组添加新对象,而非覆盖变量 $result += [pscustomobject]@{ result1 = $SlotNames[$j].deviceID result2 = $SlotNames[$j].Location result3 = $array[$i].substring(1, 19) } break } else { Write-Host 'No match!' } } }
方案2:使用泛型列表(适合大数据量,效率更高)
+=操作数组时会每次创建新数组,数据量大时性能损耗明显,推荐用泛型列表:
# 初始化泛型列表存储结果 $resultList = [System.Collections.Generic.List[PSObject]]::new() for ($i = 0; $i -lt $array.length; $i++) { $cfID = $array[$i].substring(65, 16) for ($j = 0; $j -lt $slotnames.length; $j++) { if ($slotnames[$j].deviceID.substring(22, 16) -eq $cfID) { # 向列表添加新对象 $resultList.Add([pscustomobject]@{ result1 = $SlotNames[$j].deviceID result2 = $SlotNames[$j].Location result3 = $array[$i].substring(1, 19) }) break } else { Write-Host 'No match!' } } } # 可选:将列表转为数组(如需保持数组格式) $result = $resultList.ToArray()
额外优化建议
嵌套循环的时间复杂度较高(O(n*m)),如果数组元素较多,可以先把$slotnames转换为哈希表,用匹配的ID作为键,将时间复杂度降到O(n):
# 预先构建slotnames的哈希表,key为deviceID截取的16位字符串 $slotHash = @{} foreach ($slot in $slotnames) { $key = $slot.deviceID.substring(22, 16) $slotHash[$key] = $slot } $result = @() foreach ($item in $array) { $cfID = $item.substring(65, 16) if ($slotHash.ContainsKey($cfID)) { $slot = $slotHash[$cfID] $result += [pscustomobject]@{ result1 = $slot.deviceID result2 = $slot.Location result3 = $item.substring(1, 19) } } else { Write-Host 'No match!' } }
内容的提问来源于stack exchange,提问作者Lando
相关产品推荐
相关产品推荐

