PowerShell中如何基于参考数组对目标数组完成重排序
PowerShell 按指定参考数组对目标数组排序实现
你之前使用的[Linq.Enumerable]::SequenceEqual仅能校验两个序列是否完全相等,完全不具备排序能力,返回全部4个元素是符合预期的,因为两个数组顺序本身就不一致。
核心实现逻辑
先为参考集$definedSet构建「元素值->排列位置」的键值映射,排序时以该映射值作为主键:存在于参考集的元素按预设顺序排列,不存在于参考集的元素统一分配最大排序权重放到末尾,同时支持保留非参考集元素的原有相对顺序,兼容两边存在独有元素的场景。
Linq 版本实现(符合技术选型要求)
# 测试数据,$history包含两个参考集没有的元素F、E,用于验证兼容性 $definedSet = @('C', 'B', 'D', 'A') $history = @('A', 'B', 'C', 'D', 'F', 'E') # 构建顺序映射表 $orderIndex = @{} for ($i = 0; $i -lt $definedSet.Count; $i++) { $orderIndex[$definedSet[$i]] = $i } # 执行排序 $sortedArray = [Linq.Enumerable]::OrderBy( [string[]]$history, [Func[string, int]]{ param($item) # 参考集内元素返回对应位置索引,集外元素返回int最大值放到末尾 if ($orderIndex.ContainsKey($item)) { return $orderIndex[$item] } return [int]::MaxValue } ).ThenBy( [Func[string, int]]{ param($item) # 同权重元素按原数组相对顺序排列,不需要可以删掉这段ThenBy return [array]::IndexOf($history, $item) } ).ToArray() # 输出结果为 C B D A F E $sortedArray
纯PowerShell原生写法(无需手动调用Linq)
逻辑和Linq版本完全一致,代码更简洁:
$sortedArray = $history | Sort-Object { if ($orderIndex.ContainsKey($_)) { $orderIndex[$_] } else { [int]::MaxValue } }, { [array]::IndexOf($history, $_) }
可调规则说明
- 想把参考集不存在的元素放到排序结果开头,把集外元素的返回值从
[int]::MaxValue改成[int]::MinValue即可 - 如果数组元素不是字符串类型,把Linq写法里的泛型参数
[string]替换为对应类型即可,比如整数数组替换为[int] - 参考集存在重复元素时,映射表默认取元素最后一次出现的位置作为排序依据,需要适配重复元素场景可以调整映射表构建逻辑
内容的提问来源于stack exchange,提问作者Gordon
相关产品推荐
相关产品推荐

