You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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
  }
}

关键修复细节

  1. 替换普通数组为ArrayList:PowerShell普通数组是不可变的,+=操作会创建新数组并自动展开元素;ArrayList的Add()方法可直接添加单个元素(包括数组),保留嵌套结构。
  2. 修正分组匹配逻辑:原代码中布尔值集合需判断是否存在匹配项,确保正确找到关联分组。
  3. 明确元素添加方式:用[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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 21:35:12