PowerShell是否有内置方法高效搜索唯一已排序数组/集合并返回索引?
PowerShell中已排序唯一集合的高效搜索方案
你不需要自己实现二分查找逻辑,PowerShell可以直接调用.NET框架的内置工具来完成这个需求,以下是几种实用方案:
1. 直接用Array.BinarySearch处理已排序数组
PowerShell的数组本质是.NET的System.Array,可以直接调用静态方法[Array]::BinarySearch来做O(log n)效率的二分查找,找到后返回对应索引,未找到则返回负数(按位取反后是该值应该插入的位置)。
示例:基础类型数组
# 已排序的整数数组 $sortedArray = 2, 4, 6, 8, 10 $searchValue = 6 $index = [Array]::BinarySearch($sortedArray, $searchValue) if ($index -ge 0) { "找到值,索引为: $index" } else { "未找到目标值" }
示例:自定义对象集合(SQL查询结果场景)
如果你的集合是SQL返回的自定义对象(比如带Id、Name属性),需要指定比较器来匹配排序规则(比如按Id排序的集合,就按Id比较):
# 模拟SQL返回的已排序唯一对象 $sortedObjects = @( [PSCustomObject]@{ Id = 101; Username = "user_a" }, [PSCustomObject]@{ Id = 103; Username = "user_b" }, [PSCustomObject]@{ Id = 105; Username = "user_c" } ) # 目标匹配对象 $targetObj = [PSCustomObject]@{ Id = 103; Username = "user_b" } # 创建比较器,按Id属性比较 $idComparer = [System.Collections.Generic.Comparer[PSCustomObject]]::Create({ param($objA, $objB) $objA.Id.CompareTo($objB.Id) }) $index = [Array]::BinarySearch($sortedObjects, $targetObj, $idComparer) if ($index -ge 0) { "找到匹配对象,索引: $index,用户名: $($sortedObjects[$index].Username)" } else { "未找到匹配对象" }
2. 使用.NET已排序集合类型
如果需要频繁执行查找操作,可以提前将数据存入.NET的内置已排序集合,这些集合本身维护有序状态,查找效率更高:
SortedList<TKey, TValue>:键值对场景
适合以唯一键排序的场景,支持直接通过键查找值,还能通过IndexOfKey获取键对应的索引:
# 初始化SortedList,键为Id(整数类型),值为自定义对象 $sortedList = [System.Collections.Generic.SortedList[int, PSCustomObject]]::new() $sortedObjects | ForEach-Object { $sortedList.Add($_.Id, $_) } # 查找Id=103的对象 $targetId = 103 if ($sortedList.ContainsKey($targetId)) { $foundObj = $sortedList[$targetId] $index = $sortedList.IndexOfKey($targetId) "找到对象: $($foundObj.Username),索引: $index" }
SortedSet<T>:元素存在性/匹配场景
如果只需要判断元素是否存在或获取匹配项,SortedSet<T>的查找效率也是O(log n),但它没有直接返回索引的方法:
# 初始化SortedSet,传入自定义比较器 $setComparer = [System.Collections.Generic.Comparer[PSCustomObject]]::Create({ param($a, $b) $a.Id.CompareTo($b.Id) }) $sortedSet = [System.Collections.Generic.SortedSet[PSCustomObject]]::new($setComparer) $sortedObjects | ForEach-Object { $sortedSet.Add($_) } # 检查目标对象是否存在 if ($sortedSet.Contains($targetObj)) { "找到匹配对象" }
关键注意点
- 所有方案的前提是集合必须严格按照你指定的规则排序,否则二分查找或已排序集合的逻辑会返回错误结果。
- 自定义对象的比较器必须和集合的排序规则完全一致,比如集合按
Id升序排序,比较器也要用Id的升序比较逻辑。
内容的提问来源于stack exchange,提问作者ornsio
相关产品推荐
相关产品推荐

