【问题标题】:How to keep the psobjects ordered?如何保持 psobjects 有序?
【发布时间】:2019-07-14 22:53:11
【问题描述】:

我有以下脚本,它从另一个脚本中获取对象并将其转换为 pscustomobject

& ".\script1.ps1" -ViewConnection "$cinput" -OutVariable xprtOut | Format-Table -Wrap

#converting xprtOut from Arraylist to pscustomobject to be used with ConvertTo-HTMLTable
$Arr = @()
foreach ($Object in $xprtOut) {
    $i = -1
    $arrayListCount = -($Object | gm | Where-Object {$_.MemberType -like "noteproperty"}).Count

    $customObj = New-Object PSCustomObject
    do {
        $customObj | Add-Member -MemberType NoteProperty -Name (($Object | gm)[$($i)].Name) -Value ($Object."$(($Object | gm)[$($i)].Name)")
        $i--
    } while ($i -ge $arrayListCount)

    $Arr += $customObj
}

效果很好,但我注意到对象的顺序发生了变化。 如何保留函数中的顺序?

我在这里尝试答案:https://stackoverflow.com/a/42300930/8397835

$Arr += [pscustomobject]$customObj

但这不起作用。我尝试将演员表放在函数的其他位置并给出错误。

ordered 属性只能在散列文字节点上指定。

我想我不确定我应该将[ordered][pscutomobject] 放在函数中的什么位置,因为在我的情况下我没有@ 符号

【问题讨论】:

  • @Drew 既然你策划了这个功能,你对这个排序有什么建议吗:)
  • 不要使用New-Object & Add-Member,而是使用[ordered]$Hashtable@{}$Hashtable.Add(),最后使用[PSCustomObject]$Hashtable,让事情保持顺序。 [咧嘴]
  • @Lee_Dailey 我明白了。您介意发布这些修改的答案吗?
  • @Lee_Dailey 会是 $customObj = New-Object PSCustomObject 而不是 $customObj = New-Object PSCustomObject ....?和 $Hashtable.Add(($Object | gm)[$($i)].Name) -Value ($Object."$(($Object | gm)[$($i)].Name)") ?我会用 [PSCustomObject]$Hashtable 替换 $Arr += $customObj 吗?
  • 不——不要使用New-Object。创建一个 ordered 哈希表,遍历您的集合并将项目添加到该哈希表,然后使用 PSCO 类型加速器使用[PSCustomOBject]$Hashtable 创建您的自定义对象。最后,将 PSCO 添加到您的新集合中。

标签: powershell


【解决方案1】:

这个问题(如我所见)都是关于复制对象属性同时保持属性顺序到位。
Get-Member (gm) cmdlet 不会保持在输入对象中设置属性的顺序,但会遍历 PSObject.Properties

对于 PowerShell 3.0 及更高版本:

$Arr = foreach ($Object in $xprtOut) {
    # create an empty PSCustomObject
    $copy = [PSCustomObject]::new()
    # loop through the properties in order and add them to $copy object
    $Object.PSObject.Properties | ForEach-Object { 
        $copy | Add-Member -MemberType NoteProperty -Name $_.Name -Value $_.Value
    }
    # emit the copied object so it adds to the $Arr array
    $copy
}

如果您的 PowerShell

$Arr = foreach ($Object in $xprtOut) {
    # create an ordered dictionary object
    $copy = New-Object System.Collections.Specialized.OrderedDictionary
    # loop through the properties in order and add them to the ordered hash
    $Object.PSObject.Properties | ForEach-Object { 
        $copy.Add($_.Name, $_.Value)   # or use: $copy[$($_.Name)] = $_.Value
    }
    # emit a PSObject with the properties ordered, so it adds to the $Arr array
    New-Object PSObject -Property $copy
}

【讨论】:

  • Theo,这个解决方案更加简洁和直观,让事情变得井井有条!我确实有一个问题......无论是否有 $Arr = @() 声明,您的代码都可以正常工作。这怎么可能?如果 $Arr 尚未使用 @() 定义,它又是如何成为数组的?谢谢!
  • @Cataster 这就是 PowerShell 的美妙之处。它具有将循环的输出直接捕获到变量中的能力。您将得到一个对象(如果循环只迭代一个“事物”)或一个对象数组,如本例所示。此外,首先创建一个空数组并在循环内向其中添加元素也快得多。
  • 这确实是一种美。我每天都越来越爱上 powershell。我想尝试进入 GUI powershell,因为这对我来说太有趣了。我喜欢 powershell 的一个原因是它原生于 Windows。您只需启动控制台,而无需下载任何内容。它不会像启动 Visual Studio 那样花很长时间。我可以用记事本++做所有事情:)
  • @Cataster [:thumbsup:]
猜你喜欢
  • 2015-09-03
  • 1970-01-01
  • 2018-08-09
  • 2013-11-10
  • 1970-01-01
  • 2015-06-26
  • 1970-01-01
  • 2020-04-17
  • 1970-01-01
相关资源
最近更新 更多