Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to keep the psobjects ordered?

Tags:

powershell

I have the following script that gets objects from another scripts and converts it to a 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
}

it works great and all but i notice the ordering of the objects changes. how can i preserve the ordering in the function?

i am trying the answer here: https://stackoverflow.com/a/42300930/8397835

$Arr += [pscustomobject]$customObj

but that doesnt work. i tried placing the cast elsewhere in the function and gave out errors.

The ordered attribute can be specified only on a hash literal node.

i guess i am not sure where am i supposed to place the [ordered] or [pscutomobject] in the function since in my case i dont have @ symbol

like image 652
Cataster Avatar asked Sep 20 '25 05:09

Cataster


1 Answers

This question is (as I see it) all about copying objects properties while keeping the property order in place.
The Get-Member (gm) cmdlet does not keep the order in which the properties are set in the input objects, but iterating through the PSObject.Properties does.

For PowerShell version 3.0 and above:

$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
}

If you have PowerShell < 3.0, use the code below:

$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
}
like image 159
Theo Avatar answered Sep 23 '25 05:09

Theo