algorithm - 有人有 PowerShell 的依赖关系图和拓扑排序代码片段吗?

标签 algorithm powershell msbuild dependencies powershell-2.0

我们试图通过依赖图和拓扑排序来并行化我们的构建。

我们所有的构建逻辑都是用 Msbuild 编写的,我们使用 powershell 来调用它。

有人用powershell实现过依赖图和拓扑排序吗?

我知道在 unix 中有一个名为 tsort 的实用程序可用。 powershell 中有类似的东西吗?

这篇文章提供了很好的想法,但它是用 C# 完成的"http://msdn.microsoft.com/en-us/magazine/dd569760.aspx"

最佳答案

我快速翻译了Wikipedia's Topological Sort Algorithm :

function Get-TopologicalSort {
  param(
      [Parameter(Mandatory = $true, Position = 0)]
      [hashtable] $edgeList
  )

  # Make sure we can use HashSet
  Add-Type -AssemblyName System.Core

  # Clone it so as to not alter original
  $currentEdgeList = [hashtable] (Get-ClonedObject $edgeList)

  # algorithm from http://en.wikipedia.org/wiki/Topological_sorting#Algorithms
  $topologicallySortedElements = New-Object System.Collections.ArrayList
  $setOfAllNodesWithNoIncomingEdges = New-Object System.Collections.Queue

  $fasterEdgeList = @{}

  # Keep track of all nodes in case they put it in as an edge destination but not source
  $allNodes = New-Object -TypeName System.Collections.Generic.HashSet[object] -ArgumentList (,[object[]] $currentEdgeList.Keys)

  foreach($currentNode in $currentEdgeList.Keys) {
      $currentDestinationNodes = [array] $currentEdgeList[$currentNode]
      if($currentDestinationNodes.Length -eq 0) {
          $setOfAllNodesWithNoIncomingEdges.Enqueue($currentNode)
      }

      foreach($currentDestinationNode in $currentDestinationNodes) {
          if(!$allNodes.Contains($currentDestinationNode)) {
              [void] $allNodes.Add($currentDestinationNode)
          }
      }

      # Take this time to convert them to a HashSet for faster operation
      $currentDestinationNodes = New-Object -TypeName System.Collections.Generic.HashSet[object] -ArgumentList (,[object[]] $currentDestinationNodes )
      [void] $fasterEdgeList.Add($currentNode, $currentDestinationNodes)        
  }

  # Now let's reconcile by adding empty dependencies for source nodes they didn't tell us about
  foreach($currentNode in $allNodes) {
      if(!$currentEdgeList.ContainsKey($currentNode)) {
          [void] $currentEdgeList.Add($currentNode, (New-Object -TypeName System.Collections.Generic.HashSet[object]))
          $setOfAllNodesWithNoIncomingEdges.Enqueue($currentNode)
      }
  }

  $currentEdgeList = $fasterEdgeList

  while($setOfAllNodesWithNoIncomingEdges.Count -gt 0) {        
      $currentNode = $setOfAllNodesWithNoIncomingEdges.Dequeue()
      [void] $currentEdgeList.Remove($currentNode)
      [void] $topologicallySortedElements.Add($currentNode)

      foreach($currentEdgeSourceNode in $currentEdgeList.Keys) {
          $currentNodeDestinations = $currentEdgeList[$currentEdgeSourceNode]
          if($currentNodeDestinations.Contains($currentNode)) {
              [void] $currentNodeDestinations.Remove($currentNode)

              if($currentNodeDestinations.Count -eq 0) {
                  [void] $setOfAllNodesWithNoIncomingEdges.Enqueue($currentEdgeSourceNode)
              }                
          }
      }
  }

  if($currentEdgeList.Count -gt 0) {
      throw "Graph has at least one cycle!"
  }

  return $topologicallySortedElements
}

这取决于

# Idea from http://stackoverflow.com/questions/7468707/deep-copy-a-dictionary-hashtable-in-powershell 
function Get-ClonedObject {
    param($DeepCopyObject)
    $memStream = new-object IO.MemoryStream
    $formatter = new-object Runtime.Serialization.Formatters.Binary.BinaryFormatter
    $formatter.Serialize($memStream,$DeepCopyObject)
    $memStream.Position=0
    $formatter.Deserialize($memStream)
}

然后你像这样使用它

# Sort the Wikipedia example:
Get-TopologicalSort @{11=@(7,5);8=@(7,3);2=@(11);9=@(11,8);10=@(11,3)}

产生:

7
5
3
11
8
10
2
9

关于algorithm - 有人有 PowerShell 的依赖关系图和拓扑排序代码片段吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8982782/

相关文章:

ruby - Rake 删除文件任务

python - 生成字符串代码错误的排列

algorithm - 回溯经典n皇后的时间复杂度分析

algorithm - 如何最佳地将元素放置在矩阵中,以便与其他元素的距离最小?

powershell - 如何在 PowerShell 中重命名所有文件类型中的字符串

asp.net - Visual Studio 构建错误 "Illegal characters in path"

database - 数据库是如何实现skipping的?

powershell - 使用 Jenkins 将 war 文件部署到 Tomcat 的推荐方法?

windows - 如何创建与我的 shell 在同一进程中运行的 Powershell 别名(或函数或 cmdlet)?

msbuild - 想要通过 .NET Core 项目文件中的 MSBuild 目标复制/重命名文件,但我不知道如何操作