通过比较两个对象来构建对象的代码以提升性能

后端开发 2026-07-11

我需要在PowerShell中更快地把一个对象从另一个对象构建出来。

我有一个包含10,000个主机名的PowerShell字符串数组:

$hostnames = @("server1","server2","server3"..."server10000")

还有一个包含自定义对象的PowerShell数组,其NoteProperty为 "hostname" 和 "IP"。两个Note Property都是字符串。该数组共有50,000个元素。

$inventory[0].name="server1"
$inventory[0].ip="10.0.0.1"
$inventory[1].name="server2"
$inventory[1].ip="10.0.0.2"

我需要基于 $inventory中的元素,且仅针对与 $hostnames匹配的那些元素,构建一个新对象。我写了这段代码:

$newList = @()
foreach($name in $hostnames){
    $newList += $inventory | Where-Object {$_.name -eq $name}
    }

这段代码最终能跑通。當 $hostnames中有一万個元素时,它必须遍历 $inventory的 50,000个元素一万次。这需要花费很长时间。

我该如何优化这段代码?是否应该使用.Net类来替代PowerShell的数组?除了带Where-Object的 foreach循环之外,是否还有其他算法?

解决方案

在筛选大型集合时,为了获得最佳性能,你应该避免线性比较,目前你是在对每个 $hostnames 项对 $inventory 集合进行完全循环。相反,使用基于哈希的查找,对你的 $hostnames 使用一个 Hashset<string> 的哈希集合,然后使用一个经典的 foreach 配合 if 条件进行过滤。你还应该避免在数组上进行 +=,相反从循环中输出并把循环表达式赋值给一个变量,参见 array addition

下面的代码看起来是这样的:

$hostnames = [System.Collections.Generic.HashSet[string]]::new(
    [string[]] @('server1', 'server2', 'server3', '...', 'server10000'),
    [System.StringComparer]::OrdinalIgnoreCase)

$inventory = @(
    @{ name = 'server1'; ip = '10.0.0.1' }
    @{ name = 'server2'; ip = '10.0.0.2' }
    @{ name = 'notinhostnames'; ip = '10.0.0.2' })

$invtoryObjectsInHostnames = foreach ($object in $inventory) {
    if ($hostnames.Contains($object.name)) {
        $object
    }
}

$invtoryObjectsInHostnames
# Name          Value
# ----          -----
# ip            10.0.0.1
# name          server1
# ip            10.0.0.2
# name          server2

另一种实现方式也涉及基于哈希查找,即使用一个哈希表,其每个键都是 name$inventory 中的对象的 name,然后在 $hostnames 上完成过滤循环(这与你原本打算采用的方法类似,只是要高效得多):

$hostnames = @('server1', 'server2', 'server3', '...', 'server10000')

$inventory = @(
    @{ name = 'server1'; ip = '10.0.0.1' }
    @{ name = 'server2'; ip = '10.0.0.2' }
    @{ name = 'notinhostnames'; ip = '10.0.0.2' })

$map = @{}
foreach ($object in $inventory) { $map[$object.name] = $object }

$invtoryObjectsInHostnames = foreach ($item in $hostnames) {
    if ($map.ContainsKey($item)) {
        $map[$item]
    }
}
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章