PowerShell 7(Core)无法创建含单个数组的嵌套数组问题
PowerShell嵌套数组扁平化问题及分组函数修复
问题说明
PowerShell中数组的自动扁平化特性会导致嵌套数组结构丢失:
- 包含多个子数组的嵌套数组可正常保留结构,例如
@(@('a', 'b'), @('c', 'd'))返回@(@('a', 'b'), @('c', 'd')) - 仅含单个子数组的嵌套数组会被扁平化,例如
@(@('a', 'b'))返回@('a', 'b'),使用,@(@('a', 'b'))也无法解决深层嵌套的扁平化问题 - JSON转换同样受影响:
'[["a", "b"]]' | ConvertFrom-Json | ConvertTo-Json返回["a", "b"]
在移植一个基于连接对分组元素的JavaScript函数时,这个问题导致PowerShell实现逻辑出错。
原JavaScript实现
function group(connections) { let groups = []; connections.forEach(connection => { let group = groups.find(g => g.some(item => connection.includes(item))); if (group) { const groupIndex = groups.indexOf(group); groups[groupIndex] = [...new Set([...group, ...connection])]; } else { groups.push(connection); } }); return connections.length === groups.length ? groups : group(groups); }
存在问题的PowerShell尝试
function Group-Connections { param ([Parameter(Mandatory=$true)] [Array]$connections) $groups = @() foreach ($connection in $connections) { $group = $groups | Where-Object { $_ | ForEach-Object { $connection -contains $_ } } if ($group) { $index = $groups.IndexOf($group) $groups[$index] = $group + $connection | Sort-Object -Unique } else { $groups += $($connection) } } if ($connections.Length -eq $groups.Length) { return $groups } else { return Group-Connections -connections $groups } }
执行以下代码时,预期得到嵌套数组@(@('a', 'b', 'c'), @('e', 'f')),但实际返回扁平化后的数组@("a", "b", "c", "e", "f"):
$groups = @() $groups += $group1 #@(@('a', 'b', 'c')) $groups += $group2 #@(@('e', 'f'))
解决方案
修复后的Group-Connections函数
function Group-Connections { param ([Parameter(Mandatory=$true)] [Array]$connections) # 使用ArrayList避免普通数组+=操作的扁平化问题 $groups = [System.Collections.ArrayList]::new() foreach ($connection in $connections) { # 查找与当前连接对有交集的分组 $matchingGroup = $groups | Where-Object { ($_ | Where-Object { $connection -contains $_ }) -ne $null } if ($matchingGroup) { $index = $groups.IndexOf($matchingGroup) # 合并分组并去重,更新列表 $merged = ($matchingGroup + $connection) | Sort-Object -Unique $groups[$index] = $merged } else { # 将数组作为单个元素添加,避免自动展开 [void]$groups.Add($connection) } } if ($connections.Count -eq $groups.Count) { return $groups } else { return Group-Connections -connections $groups } }
关键修复细节
- 替换普通数组为ArrayList:PowerShell普通数组是不可变的,
+=操作会创建新数组并自动展开元素;ArrayList的Add()方法可直接添加单个元素(包括数组),保留嵌套结构。 - 修正分组匹配逻辑:原代码中布尔值集合需判断是否存在匹配项,确保正确找到关联分组。
- 明确元素添加方式:用
[void]$groups.Add($connection)确保子数组作为单个元素存入,避免扁平化。
测试示例
# 测试输入:包含关联和独立的连接对 $connections = @( @('a', 'b'), @('b', 'c'), @('d', 'e'), @('f', 'g') ) # 执行分组 $result = Group-Connections -connections $connections # 输出结果:@(@('a','b','c'), @('d','e'), @('f','g')) $result
手动创建单元素嵌套数组的方法
如果需要手动构造单元素嵌套数组,可使用以下方式:
- ArrayList方式:
$nested = [System.Collections.ArrayList]::new() $nested.Add(@('a','b')) | Out-Null - 强制类型方式:
$nested = [array[]]@(@('a','b')) - 逗号操作符方式:
$nested = ,@('a','b')
内容的提问来源于stack exchange,提问作者Dipo
相关产品推荐
相关产品推荐

