【问题标题】:How to join two object arrays in Powershell如何在 Powershell 中加入两个对象数组
【发布时间】:2020-08-25 09:12:25
【问题描述】:

我的 powershell 脚本中有两个对象数组

第一个具有这样的值

@{Id=1, Count=24}
@{Id=2, Count=34}

第二

@{Id=1, Name="Some name"}
@{Id=2, Name="Some other name"}

我喜欢加入这两个所以我得到

@{Id=1, Count=24 Name="Some name"}
etc

最终我需要将其写入 csv 文件。

【问题讨论】:

  • 请编辑问题并显示这些值是如何分配的。这些变量看起来有点像哈希表,但语法不完全一样。

标签: powershell


【解决方案1】:

使用此Join-Object cmdlet(另请参阅:In Powershell, what's the best way to join two tables into one?)其中(自定义)对象(包括数据表)和哈希表:

$Array1 = @{Id=1; Count=24},
          @{Id=2; Count=34}
    
$Array2 = @{Id=1; Name="Some name"},
          @{Id=2; Name="Some other name"}

$Array1 | Join $Array2 -On Id

Count Id Name
----- -- ----
   24  1 Some name
   34  2 Some other name

【讨论】:

    【解决方案2】:

    对于来自 google 的子孙后代,这是解决问题的惯用方法。

    $first = $(
        @{Id=1; Count=24}
        @{Id=2; Count=34}
    )
    $second = $(
        @{Id=1; Name="Some name"}
        @{Id=2; Name="Some other name"}
    )
    
    $first,$second `
    | %{ $_ } `
    | To-Object `
    | Group-Object -Property Id `
    | %{ $_.Group | To-Hash | Merge } `
    | To-Object `
    | ConvertTo-Csv
    

    如果您想将它们保留为哈希表并且暂时不获取 CSV,请删除最后两行,或者如果它们是开始的对象,请删除第一个 To-Object

    您需要以下内容:

    Filter To-Object {
        $output = [PSCustomObject]@{}
        $_.GetEnumerator() `
        | %{
            $output `
            |  Add-Member `
                -Type NoteProperty `
                -Name $_.Name `
                -Value $_.Value
        }
        $output
    }
    
    Filter To-Hash {
        $out = @{}
        $in = $_
        $in `
        | Get-Member -MemberType NoteProperty `
        | %{
            $out[$_.Name] = $in.($_.Name)
        }
        $out
    }
    
    Function Merge {
        Begin {
            $output = @{}
        }
        Process {
            $_.GetEnumerator() `
            | %{
                $output[$_.Name] = $_.Value
            }
        }
        End {
            $output
        }
    }
    

    不如我的其他答案(专为目的而构建)那么有效,但这些对于提问者的确切用例之外的东西会更有用,并且对于任何学习 powershell 的人来说都会更好看:)

    【讨论】:

    • 有趣的方法。改进的想法:1) 将To-Object 简化为{ New-Object PSCustomObject -Property $_ } 2) 通过重组Merge 来处理对象,从而抛弃To-Hash
    【解决方案3】:

    如果你的数组有 objects 就像你说的那样

    $array1 = [PsCustomObject]@{Id=1; Count=24}, 
              [PsCustomObject]@{Id=2; Count=34}
    $array2 = [PsCustomObject]@{Id=1; Name="Some name"}, 
              [PsCustomObject]@{Id=2; Name="Some other name"}
    

    你可以这样做:

    # this updates the objects in $array1
    foreach ($item in $array1) {
        foreach ($obj in $item) {
            $obj | Add-Member -MemberType NoteProperty -Name 'Name' -Value ($array2 | Where-Object { $_.Id -eq $obj.Id }).Name
        }
    }
    
    # show on screen
    $array1
    
    # export to CSV
    $array1 | Export-Csv -Path 'D:\Test\Joined.Csv' -NoTypeInformation
    

    屏幕输出:

    Id 计数名称 -- ----- ---- 1 24 一些名字 2 34 其他名称

    如果数组存储 Hashtables 喜欢

    $array1 = @{Id=1; Count=24}, 
              @{Id=2; Count=34}
    $array2 = @{Id=1; Name="Some name"}, 
              @{Id=2; Name="Some other name"}
    

    然后使用这个:

    # this returns a new array of PSObjects
    $result = foreach ($item in $array1) {
        foreach ($hash in $item) {
            $hash['Name'] = ($array2 | Where-Object { $_.Id -eq $hash.Id }).Name
        }
        [PsCustomObject]$hash
    }
    
    # show on screen
    $result
    
    # export to CSV
    $result | Export-Csv -Path 'D:\Test\JoinedFromHashes.Csv' -NoTypeInformation
    

    屏幕输出:

    名称 ID 计数 ---- -- ----- 一些名字 1 24 其他名称 2 34

    请注意,哈希表默认是无序的,因此列出现的顺序可能会有所不同

    【讨论】:

      【解决方案4】:
      $first = $(
          @{Id=1; Count=24}
          @{Id=2; Count=34}
      )
      $second = $(
          @{Id=1; Name="Some name"}
          @{Id=2; Name="Some other name"}
      )
      
      $first,$second `
      | %{ $_ } `
      | &{
          Param ($key)
          Begin {
              $output = @{}
              
              Function Input {
                  Param ($id)
                  Begin {
                      $merged = $output[$id]
                      if (!$merged) {
                          $merged = [PSCustomObject]@{$key=$id}
                      }
                  }
                  Process {
                      if ($_.Name -ne $key) {
                          $merged `
                          |  Add-Member `
                              -Type NoteProperty `
                              -Name $_.Name `
                              -Value $_.Value
                      }
                  }
                  End {
                      $output[$id] = $merged
                  }
              }
          }
          Process {
              $_.GetEnumerator() `
              | Input -id $_[$key]
          }
          End {
              $output.Values
          }
      } -key 'Id' `
      | ConvertTo-Csv
      

      输出

      Id Count Name
      -- ----- ----
       2    34 Some other name
       1    24 Some name
      

      然后

      "Id","Count","Name"
      "2","34","Some other name"
      "1","24","Some name"
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-09-06
        • 1970-01-01
        • 2017-05-05
        • 2017-03-09
        • 2020-12-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多