【问题标题】:powershell comparison operator contain vs large arraypowershell比较运算符包含vs大数组
【发布时间】:2023-03-28 20:38:01
【问题描述】:

想知道是否有机会提高以下数组搜索的性能。现在是 16 秒。

Measure-Command -Expression {

$a = @()
$b = @()
1..10000 | %{$a += $_}
1..10000 | %{$b += $_}

#Try to resize but still running 16 seconds
[array]::Resize([ref]$a,10000) 
[array]::Resize([ref]$b,10000)

foreach ($i in $a){
    if ($b -contains $i) {
        #write-host $i
    }
}

}

【问题讨论】:

    标签: arrays powershell comparison-operators


    【解决方案1】:
    1. += 在数组的情况下重新创建整个数组:它将旧内容与新元素一起复制到新数组中。这可以说是在 PowerShell 中填充大型数组的最糟糕的方法。 += 仅当它是一次性操作而不是在循环内,或者数组很小并且时间无关紧要时才使用。

      直接填充数组:

      $a = 1..10000
      

      或者直接收集foreach语句的输出:

      $a = foreach ($i in 1..10000) { $i }
      

      或者使用 ArrayList:

      $a = [Collections.ArrayList]@()
      foreach ($i in 1..10000) { $a.Add($i) >$null }
      

      注意,在这种特殊情况下,将现有数组转换为 ArrayList 会更快:

      $a = [Collections.ArrayList]@(1..10000)
      

       

    2. 流水线是一项复杂的操作,它比foreach(语句,不是 cmdlet)、whiledo 等流控制语句慢几倍/几倍。

       

    3. ScriptBlock(ForEach cmdlet 中的花括号 { } 中的代码,别名为 %)与简单代码相比,为每个元素创建执行上下文需要大量时间里面。

       

    4. -contains 检查每个元素,直到找到匹配项,因此最终迭代次数在最坏情况下为 $a.count * $b.count,或平均为一半。

       

    最有效的方法是建立一个查找表:

    • 作为哈希表:

      $a = 1..10000
      $b = 1..10000
      
      $bIndex = @{}
      foreach ($i in $b) { $bIndex[$i] = $true }
      
      foreach ($i in $a) {
          if ($bIndex[$i]) {
              #write-host $i
          }
      }
      

      在 i7 CPU 上为 15 毫秒

    • 作为 HashSet(.NET 3.5 和更新版本,built-in since Win7,可在 XP 上安装):

      $a = 1..10000
      $b = 1..10000
      
      $bIndex = [Collections.Generic.HashSet[int]]$b
      
      foreach ($i in $a) {
          if ($bIndex.Contains($i)) {
              #write-host $i
          }
      }
      

      i7 CPU 上 7 毫秒

    • 使用 HashSet 将数组相交,然后迭代结果:

      $a = 1..10000
      $b = 1..10000
      
      $inBoth = [Collections.Generic.HashSet[int]]$a
      $inBoth.IntersectWith([Collections.Generic.HashSet[int]]$b)
      foreach ($i in $inBoth) {
          #write-host $i
      }
      

      i7 CPU 上 7 毫秒

      如果数组的内容不同,即交集比数组小很多时,它会快很多倍。

    还可以在数组中构建一个真正的index that contains a list of original item indices - 在重复值的情况下很有用。

    【讨论】:

      猜你喜欢
      • 2013-12-28
      • 1970-01-01
      • 2012-01-26
      • 2021-06-16
      • 1970-01-01
      • 1970-01-01
      • 2013-08-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多