如何在PowerShell中基于ID映射合并两个数组并生成结果数组
嘿,作为PowerShell新手,刚接触数组匹配和对象改造确实会有点懵,别担心,我给你一个清晰的实现方案,还会一步步解释每部分的作用!
你的场景回顾
两个REST请求获取数据
# 第一个请求 $MyResultArray1 = Invoke-RestMethod -Uri "http://myhost/rest-api-1" -Method GET -ErrorAction 'Stop' # 第二个请求 $MyResultArray2 = Invoke-RestMethod -Uri "http://myhost/rest-api-2" -Method GET -ErrorAction 'Stop'
返回的数组结构
Array 1 - $MyResultArray1
{ "values": [ { "id": 1, "testType": "something1" }, { "id": 2, "testType": "something2" }, { "id": 3, "testType": "something3" } ] }
Array 2 - $MyResultArray2
{ "values": [ { "testId": 1, "testResult": "result1", "testMeta": {} }, { "testId": 2, "testResult": "result2", "testMeta": {} }, { "testId": 3, "testResult": "result3", "testMeta": {} } ] }
目标合并结果
Array 3 - $Result
{ "result": [ { "id": 1, "testType": "something1", "testResult": "result1" }, { "id": 2, "testType": "something2", "testResult": "result2" }, { "id": 3, "testType": "something3", "testResult": "result3" } ] }
实现步骤与代码
核心思路是先把第二个数组的数据转成哈希表(Dictionary),这样根据testId查找对应的testResult会非常高效,避免嵌套遍历的低效操作,然后再遍历第一个数组的每个对象,匹配后添加字段。
# 1. 把$MyResultArray2的values转成哈希表,key是testId,value是testResult $testResultLookup = @{} foreach ($item in $MyResultArray2.values) { $testResultLookup[$item.testId] = $item.testResult } # 2. 遍历$MyResultArray1的values,为每个对象添加testResult字段 $mergedItems = foreach ($item in $MyResultArray1.values) { # 复制原对象(避免修改原数组的数据) $newItem = $item.PSObject.Copy() # 查找匹配的testResult,找不到的话可以设为默认值比如$null $newItem | Add-Member -MemberType NoteProperty -Name "testResult" -Value $testResultLookup[$item.id] -Force # 返回处理后的对象 $newItem } # 3. 包装成你需要的结果结构 $Result = [PSCustomObject]@{ result = $mergedItems } # 可以输出看看结果 $Result | ConvertTo-Json -Depth 10
代码解释
- 哈希表构建:
$testResultLookup相当于一个快速查询的字典,把testId作为键,testResult作为值,这样后面查找的时候直接用$testResultLookup[$id]就能瞬间拿到结果,比每次遍历第二个数组快很多。 - 对象复制:用
$item.PSObject.Copy()复制原对象,是为了不修改原始的$MyResultArray1数据,保持原数据的干净。 - 添加字段:
Add-Member命令用来给自定义对象添加新的属性(这里是testResult),-Force参数确保如果属性已经存在的话会覆盖,避免报错。 - 结果包装:最后用
[PSCustomObject]创建符合你要求的结构,把处理后的数组放到result字段里。
如果有些id在第二个数组里找不到对应的testId,你可以给testResult设个默认值,比如把$testResultLookup[$item.id]改成$testResultLookup[$item.id] ?? "No Result",这样找不到的时候就显示"No Result"。
内容的提问来源于stack exchange,提问作者User7723337
相关产品推荐
相关产品推荐

