How do I format array of hastables into a Table?

Hello,

How do I format into a table such a structure where columns in table will be Hashtable’s indexes

Code

$array = @();
$hashtable = @{Col1="1"; Col2="2"};
$array += $hashtable;
$array += $hashtable;
$array | ft

Output

Name                           Value                                                                                                                
----                           -----                                                                                                                
Col2                           2                                                                                                                    
Col1                           1                                                                                                                    
Col2                           2                                                                                                                    
Col1                           1  

Desired Output

Col1 Col2
1 2
1 2

You need to turn your hashtables into objects with Col1 and Col2 as properties. As it turns out, that’s incredibly easy:

# PowerShell 3.0 and later:

$array | ForEach-Object { [pscustomobject] $_ } | Format-Table

# PowerShell 2.0-compatible:

$array | ForEach-Object { New-Object -TypeName psobject -Property $_ } | Format-Table

This did not work. I’m V4

$array = @();
$hashtable = @{Col1="1"; Col2="2"};
$array += $hashtable;
$array += $hashtable;
$array | ForEach-Object { [pscustomobject] $_ } | Format-Table

output

Name                           Value                                                                                                                
----                           -----                                                                                                                
Col2                           2                                                                                                                    
Col1                           1                                                                                                                    
Col2                           2                                                                                                                    
Col1                           1                                                                                                                    


Don’t know what to tell you. I ran the code before I posted, and it works fine for me.

How is this possible? This works for you?

I’m not seeing an image in your last post, but here’s what works for me. I’m running the latest preview of PowerShell 5.0, but as far as I know, nothing’s changed with the way this works since v3. (I don’t have any older systems online at the moment to test, though).

Here is the image

https://drive.google.com/file/d/0B8pAWfQm4KqYcVExbGdRc0dHSmM/view?usp=sharing

Not working in PS 4.0

Well, do it the other way, then. :slight_smile:

Yes, v2 way works but I do have v4 though

PS C:\WINDOWS\system32> $PSVersionTable

Name Value


PSVersion 4.0
WSManStackVersion 3.0
SerializationVersion 1.1.0.1
CLRVersion 4.0.30319.34014
BuildVersion 6.3.9600.17090
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0}
PSRemotingProtocolVersion 2.2

I’m seeing the same thing, so it’s not just your PowerShell misbehaving.

PS C:\Users\Martin> $array = @();
$hashtable = @{Col1="1"; Col2="2"};
$array += $hashtable;
$array += $hashtable;
$array | ForEach-Object { [pscustomobject] $_ } | Format-Table

Name                           Value                                                                                                                                  
----                           -----                                                                                                                                  
Col2                           2                                                                                                                                      
Col1                           1                                                                                                                                      
Col2                           2                                                                                                                                      
Col1                           1                                                                                                                                      



PS C:\Users\Martin> $array = @();
$hashtable = @{Col1="1"; Col2="2"};
$array += $hashtable;
$array += $hashtable;
$array | ForEach-Object { New-Object psobject -Property $_ } | Format-Table



Col2                                                                                Col1                                                                              
----                                                                                ----                                                                              
2                                                                                   1                                                                                 
2                                                                                   1                                                                                 



PS C:\Users\Martin> $Host


Name             : Windows PowerShell ISE Host
Version          : 4.0
InstanceId       : 95a1a0f8-a342-44e6-a47e-5a2cdc5ae206
UI               : System.Management.Automation.Internal.Host.InternalHostUserInterface
CurrentCulture   : en-US
CurrentUICulture : en-US
PrivateData      : Microsoft.PowerShell.Host.ISE.ISEOptions
IsRunspacePushed : False
Runspace         : System.Management.Automation.Runspaces.LocalRunspace

But with that said, I never liked the typecasting approach, and New-Object is faster anyway.

Fiddling around with it, I see that I can typecast the $hashtable variable, but I can’t typecast the pipeline object taken from an array of hashtables. Interesting.

PS C:\Users\Martin> [pscustomobject]$array[0]

Col2                                                                                Col1                                                                              
----                                                                                ----                                                                              
2                                                                                   1                                                                                 



PS C:\Users\Martin> $array | foreach { [pscustomobject]$_ }

Name                           Value                                                                                                                                  
----                           -----                                                                                                                                  
Col2                           2                                                                                                                                      
Col1                           1                                                                                                                                      
Col2                           2                                                                                                                                      
Col1                           1                                                                                                                                      



PS C:\Users\Martin> $array | foreach { $_.GetType() }

IsPublic IsSerial Name                                     BaseType                                                                                                   
-------- -------- ----                                     --------                                                                                                   
True     True     Hashtable                                System.Object                                                                                              
True     True     Hashtable                                System.Object                                                                                              



PS C:\Users\Martin> $array[0].GetType()

IsPublic IsSerial Name                                     BaseType                                                                                                   
-------- -------- ----                                     --------                                                                                                   
True     True     Hashtable                                System.Object          

Actually typecasting is faster. Damn.

It appears to be a bug when piping into the ForEach-Object cmdlet. I can’t seem to reproduce it using any other looping method.

PS C:\Users\Martin> foreach($item in $array) { [pscustomobject]$item }

Col2                                                                                Col1                                                                              
----                                                                                ----                                                                              
2                                                                                   1                                                                                 
2                                                                                   1                                                                                 

PS C:\Users\Martin> $array.ForEach({ [pscustomobject]$_ })

Col2                                                                                Col1                                                                              
----                                                                                ----                                                                              
2                                                                                   1                                                                                 
2                                                                                   1                                                                                 

Even passing a single item into ForEach-Object fails

PS C:\Users\Martin> $array[0] | ForEach-Object { [pscustomobject]$_ }

Name                           Value                                                                                                                                  
----                           -----                                                                                                                                  
Col2                           2                                                                                                                                      
Col1                           1