如何在 Powershell 中将对象集合转换为另一种类型的新对象集合?

How does one Transform a Collection of Objects into a Collection of new Objects of another Type in Powershell?

假设我有一个方法可以获取我的枚举类型 ProjectName 的枚举集合,并且有一个 Server 对象的集合,我想将这些 ProjectName 关联到一个叫做 Project 的类型;我如何在 Powershell Select-Object(或 LINQ 的 Select 的其他等效项)中执行此操作。

我想在 Powershell 中生成的 C# 等价物是这样的:

var servers = new[]
{
    new Server(/*someOtherProjectsCollection goes here*/),
    new Server(/*someOtherProjectsCollection goes here*/),
    new Server(/*someOtherProjectsCollection goes here*/)
};
var projects = GetProjectNames().Select(projectName => new Project(projectName, servers.Where(server => server.Projects.Any(serverProject => serverProject.Name == projectName))));

但是我有的是:

$servers = [Server]::new(/*someOtherProjectsCollection goes here*/), [Server]::new(/*someOtherProjectsCollection goes here*/), [Server]::new(/*someOtherProjectsCollection goes here*/)

$projects = (GetProjectNames()) | Select-Object {
    $selectedProjectName = $_

    return [Project]::new($_, ($servers | Where-Object { $_.projects.Where({ $_ -eq $selectedProjectName }).Count -gt 0 }))
}

当我尝试在 Powershell LSE 中读取 $projects 时(在最后一行之后的断点上),它只是 returns 代码作为字符串,我什至无法转换它至 [Project[]]。我认为问题可能出在 Select-Object 中使用大括号,但我不确定如何在 Select-Object.

中创建新的 Project 对象

您希望 ForEach-Object 而不是 Select-Object 到 return 每个项目名称的新 [Project] 实例;另外,您的代码可以精简:

$projects = GetProjectNames | ForEach-Object {
    $projectName = $_
    [Project]::new(
      $projectName, 
      $servers.Where({ $_.projects -eq $projectName })
    )
}
  • Select-Object 用于根据输入对象的 select 属性创建新的自定义对象;相比之下,您正在从每个输入对象构造一个新的特定类型实例,这必须在 ForEach-Object 调用中完成,您可以在其中明确控制输出。

  • $_.projects -eq $projectName 作为条件依赖于 PowerShell 使用 -eqarray 作为 LHS 的能力,在这种情况下 过滤,过滤后的子数组被return编辑;因为 .Where() 将脚本块的输出解释为 布尔值 ,空子数组被解释为 $false,而具有至少一个元素的子数组被解释为 $true.

  • 另请注意,考虑到 PowerShell 的 隐式输出 行为,您不需要显式 return:因为新构造的 [Project] 实例未分配给变量或发送到其他地方,它会自动 returned.