Author Posts

March 14, 2015 at 5:22 am

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

March 14, 2015 at 5:40 am

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

March 14, 2015 at 5:48 am

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                                                                                                                    


March 14, 2015 at 6:17 am

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

March 14, 2015 at 6:26 am

How is this possible? This works for you?

March 14, 2015 at 9:42 am

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).

March 14, 2015 at 9:48 am

Well, do it the other way, then. 🙂

March 14, 2015 at 9:50 am

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

March 15, 2015 at 12:24 am

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.

March 15, 2015 at 12:42 am

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