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

如何在PowerShell中编辑hashtable列表并实现去重与最优项筛选?

PowerShell哈希表列表编辑优化方案

我正在寻找PowerShell中编辑哈希表列表的更优方法,目前已能遍历列表检测重复项,但不确定如何编辑哈希表并更新列表,且希望能支持大规模操作。

测试数据

测试数据格式如下(实际环境就是这种格式):

$TEST_DATA = @(
  "CA>TORONTO>MAP-LAYOUT-1",        `
  "US>NEW-YORK>MAP-LAYOUT-25",      `
  "US>DENVER>MAP-LAYOUT-2",         `
  "UK>LODNON>MAP-LAYOUT-2",         `
  "EU>PARIS>MAP-LAYOUT-25",         `
  "EU>VENICE>MAP-LAYOUT-2",         `
  "EU>BERLIN>MAP-LAYOUT-8",         `
  "EU>PARIS>MAP-LAYOUT-30",         `
  "EU>VENICE>NEW-MAP-LAYOUT-2",     `
  "EU>ATHENS>NEW-MAP-LAYOUT-8",     `
  "CA>TORONTO>NEW-MAP-LAYOUT-1",    `
  "CA>VANCOUVER>MAP-LAYOUT-1",      `
  "US>MIAMI>MAP-LAYOUT-25",         `
  "RU>MOSCOW>MAP-LAYOUT-2",         `
  "RU>ST-PETERSBURG>MAP-LAYOUT-2",  `
  "JP>TOKYO>MAP-LAYOUT-25",         `
  "EU>PARIS>MAP-LAYOUT-100",        `
  "AU>SYDNEY>MAP-LAYOUT-3",         `
  "AU>PERTH>MAP-LAYOUT-3",          `
  "MX>MEXICO-CITY>MAP-LAYOUT-5",    `
  "MX>TIJAUNA>MAP-LAYOUT-1",        `
  "CN>SHANGHAI>MAP-LAYOUT-8",       `
  "CA>CALGARY>MAP-LAYOUT-1" 
  )

当前脚本

我目前的PowerShell脚本如下:

$MAPS = @()

$TEST_DATA | Foreach {
  $COUNTRY = ($_).split('>')[0]
  $CITY = ($_).split('>')[1]
  $MAP = ($_).split('>')[2] 

  If ( $MAPS.count -gt 0) {
    $MAPS | Foreach {
      $MAPS_ROW = $_
      Write-Host $MAPS_ROW
      If (( $MAPS_ROW.COUNTRY -eq $COUNTRY ) -and ( $MAPS_ROW.CITY -eq $CITY )) {
        Write-Host '--------' -ForegroundColor Red
        Write-Host "CONFLICT DETECTED ! "
        write-Host '--------' -ForegroundColor Red
        Write-Host ""
        Write-Host "CONFLICT MAP : $MAPS_ROW"
        Write-Host ""
        If (($MAP.lenght -gt $MAPS_ROW.MAP.length) -or ( $MAP.lenght -gt ($MAPS_ROW.MAP.trim("NEW-")).length)) {
          $MAPS.Remove($MAPS_ROW)
          $NEW_MAP = New-Object PSObject -property @{ COUNTRY="$COUNTRY"; CITY="$CITY"; MAP="$MAP"; }
          $MAPS += $NEW_MAP
        } else {
          Write-Host '--------' -ForegroundColor Yellow
          Write-Host "FALSE MAP CONFLICT DETECHED !  $MAPS_ROW "
          Write-Host '--------' -ForegroundColor Yellow
        }
      } else {
        Write-Host '--------' -ForegroundColor BLue
        Write-Host "NOT IN : 'MAPS'"
        Write-Host '--------' -ForegroundColor Blue
      }
    }
    $NEW_MAP = New-Object PSObject -property @{ COUNTRY="$COUNTRY"; CITY="$CITY"; MAP="$MAP"; }
    $MAPS += $NEW_MAP
  } else { 
    Write-Host '--------' -ForegroundColor BLue
    Write-Host "First MAP Entry"
    Write-Host '--------' -ForegroundColor Blue
    $NEW_MAP = New-Object PSObject -property @{ COUNTRY="$COUNTRY"; CITY="$CITY"; MAP="$MAP"; }
    $MAPS += $NEW_MAP
  } 
}
$SORTED_MAPS = $MAPS | Sort-Object { $_.COUNTRY },  { $_.CITY }, { $_.MAP } | Select-Object @{n="COUNTRY";e={$_.COUNTRY}}, @{n="CITY";e={$_.CITY}}, @{n="MAP";e={$_.MAP}}

Write-Host '--------' -ForegroundColor Blue
$SORTED_MAPS
Write-Host '--------' -ForegroundColor Blue

当前输出结果

当前脚本运行后生成的排序列表:

COUNTRY CITY          MAP               
------- ----          ---               
AU      PERTH         MAP-LAYOUT-3      
AU      SYDNEY        MAP-LAYOUT-3      
CA      CALGARY       MAP-LAYOUT-1      
CA      TORONTO       MAP-LAYOUT-1      
CA      TORONTO       NEW-MAP-LAYOUT-1 
CA      VANCOUVER     MAP-LAYOUT-1      
CN      SHANGHAI      MAP-LAYOUT-8      
EU      ATHENS        NEW-MAP-LAYOUT-8 
EU      BERLIN        MAP-LAYOUT-8      
EU      PARIS         MAP-LAYOUT-100    
EU      PARIS         MAP-LAYOUT-25     
EU      PARIS         MAP-LAYOUT-30
EU      VENICE        MAP-LAYOUT-2      
EU      VENICE        NEW-MAP-LAYOUT-2 
JP      TOKYO         MAP-LAYOUT-25     
MX      MEXICO-CITY   MAP-LAYOUT-5      
MX      TIJAUNA       MAP-LAYOUT-1      
RU      MOSCOW        MAP-LAYOUT-2      
RU      ST-PETERSBURG MAP-LAYOUT-2      
UK      LODNON        MAP-LAYOUT-2      
US      DENVER        MAP-LAYOUT-2      
US      MIAMI         MAP-LAYOUT-25     
US      NEW-YORK      MAP-LAYOUT-25     

存在的问题

  • 如何从列表中移除重复项?尝试过Sort-Object -Unique但未成功。
  • 如何确保每个城市仅保留一个条目,且对应最优的MAP名称?筛选规则:含"NEW-"标签的MAP优先级最高;其次选择编号最大的MAP(如巴黎应保留MAP-LAYOUT-100)。曾尝试检查Country和City字段,但无法顺利对数组中的哈希表进行增删操作。
  • 是否创建新的ArrayList来处理MAP排序会更合适?

解决方案

1. 高效去重并筛选最优MAP条目

不用手动遍历检测冲突,直接用Group-Object按Country和City分组,然后对每组内的条目按规则排序,取最优的那个。这种方法代码更简洁,效率更高,适合大规模数据:

# 处理测试数据,转换为自定义对象并提取排序关键字
$processedData = $TEST_DATA | ForEach-Object {
    $parts = $_ -split '>'
    [PSCustomObject]@{
        Country = $parts[0]
        City    = $parts[1]
        Map     = $parts[2]
        IsNew   = $parts[2] -match '^NEW-'  # 标记是否为NEW-开头的MAP
        MapNum  = [int]($parts[2] -split '-')[-1]  # 提取MAP的编号数字
    }
}

# 按Country+City分组,每组内按优先级排序(NEW-优先,编号降序),取第一个最优条目
$finalMaps = $processedData | Group-Object Country,City | ForEach-Object {
    $_.Group | Sort-Object -Property IsNew -Descending, MapNum -Descending | Select-Object -First 1 -Property Country,City,Map
}

# 最终排序输出
$finalMaps | Sort-Object Country,City | Format-Table -AutoSize

运行后输出会自动每个城市只保留最优条目:

Country City          Map               
------- ----          ---               
AU      PERTH         MAP-LAYOUT-3      
AU      SYDNEY        MAP-LAYOUT-3      
CA      CALGARY       MAP-LAYOUT-1      
CA      TORONTO       NEW-MAP-LAYOUT-1 
CA      VANCOUVER     MAP-LAYOUT-1      
CN      SHANGHAI      MAP-LAYOUT-8      
EU      ATHENS        NEW-MAP-LAYOUT-8 
EU      BERLIN        MAP-LAYOUT-8      
EU      PARIS         MAP-LAYOUT-100    
EU      VENICE        NEW-MAP-LAYOUT-2 
JP      TOKYO         MAP-LAYOUT-25     
MX      MEXICO-CITY   MAP-LAYOUT-5      
MX      TIJAUNA       MAP-LAYOUT-1      
RU      MOSCOW        MAP-LAYOUT-2      
RU      ST-PETERSBURG MAP-LAYOUT-2      
UK      LODNON        MAP-LAYOUT-2      
US      DENVER        MAP-LAYOUT-2      
US      MIAMI         MAP-LAYOUT-25     
US      NEW-YORK      MAP-LAYOUT-25     

2. 关于ArrayList的使用

如果处理十万级以上的大规模数据,用ArrayList比普通数组更高效。因为普通数组是固定大小的,每次+=操作都会创建新数组并复制原有数据,数据量越大越慢。而ArrayList支持动态添加/删除元素,操作效率更高。

示例用法:

# 创建ArrayList实例
$mapList = New-Object System.Collections.ArrayList

$TEST_DATA | ForEach-Object {
    $parts = $_ -split '>'
    $entry = [PSCustomObject]@{
        Country = $parts[0]
        City    = $parts[1]
        Map     = $parts[2]
    }
    # 添加元素到ArrayList,[void]用于屏蔽Add方法返回的索引值
    [void]$mapList.Add($entry)
}

# 示例:移除第一个元素
$mapList.RemoveAt(0)

但对于你的需求,用前面的Group-Object+Sort-Object方法已经足够高效,不需要手动用ArrayList处理增删,除非你有更复杂的实时编辑需求。

3. 为什么Sort-Object -Unique没生效

Sort-Object -Unique是根据排序后的整个对象或指定属性去重,你之前的排序是按Country、City、Map,同一Country+City下的Map值不同,所以不会被去重。要实现按Country+City去重并保留最优项,必须先分组再筛选,而不是直接用-Unique参数。

内容的提问来源于stack exchange,提问作者Mr. E

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 18:24:26